A technical question concerning distributed transactions via a SQL Server "linked server" definition, using Liquibase.
background/context :
liquibase.properties
classpath=C:\\Program Files\\Microsoft SQL Server\\sqljdbc_10.2\\enu\\mssql-jdbc-10.2.0.jre8.jar
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://localhost:1433;database=SSReporting;Enlist=false
liquibaseSchemaName=dbo
username=deploy_dbbuild
password=deploy_dbbuild
changeLogFile=changelog.xml
liquibase.hub.mode=off
integratedSecurity=false
changelog.xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd">
<changeSet runOnChange="true" author="smcintosh" id="dw-1042-distributed-trans-error-v2.sql">
<sqlFile path="dw-1042-distributed-trans-error-v2.sql" relativeToChangelogFile="true" endDelimiter="GO"/>
</changeSet>
</databaseChangeLog>
dw-1042-distributed-trans-error-v2.sql
use SSReporting
go
set xact_abort on;
go
set nocount on;
go
begin
-- distributed transaction test
print formatmessage('%s START: %s', convert(varchar(20),getdate(),20), convert(varchar(67),@@version));
update RPTDB_XE..OWBTGT.DISTRIB_TRANSACTION_TEST_SCOTT set OBJECT_ID=OBJECT_ID+1;
print formatmessage('%s Updated RPTDB_XE..OWBTGT.DISTRIB_TRANSACTION_TEST_SCOTT: %d rows', convert(varchar(20),getdate(),20), @@rowcount);
insert into dbo.TASK_DETAIL_LOG (BATCH_ID, LOG_DTM, CATEGORY, SEVERITY, ACTION, TASK, SUBTASK, MSG)
values (0,getdate(),'DISTRIB_TRANS','INFO','LIQUIBASE_MIGRATE','PERFORMANCE',null,
'DISTRIB_TRANSACTION_TEST_SCOTT has been updated.');
print formatmessage('%s Inserted dbo.TASK_DETAIL_LOG : %d rows',convert(varchar(20),getdate(),20), @@rowcount);
print formatmessage('%s END', convert(varchar(20),getdate(),20));
end;
go
Run the script manually to verify that it works, using sqlcmd...
C:\>sqlcmd -Usa -Pxxxx -S tcp:SCOTT-MCINTOSH,1433 -dSSReporting -w 1000 -i dw-1042-distributed-trans-error-v2.sql
Changed database context to 'SSReporting'.
2022-03-23 13:52:08 START: Microsoft SQL Server 2019 (RTM-GDR) (KB4583458) - 15.0.2080.9 (X64)
2022-03-23 13:52:08 Updated RPTDB_XE..OWBTGT.DISTRIB_TRANSACTION_TEST_SCOTT: 3 rows
2022-03-23 13:52:08 Inserted dbo.TASK_DETAIL_LOG : 1 rows
2022-03-23 13:52:08 END
Run the script using Liquibase...
C:\>liquibase --defaults-file=liquibase.properties update
####################################################
## _ _ _ _ ##
## | | (_) (_) | ##
## | | _ __ _ _ _ _| |__ __ _ ___ ___ ##
## | | | |/ _` | | | | | '_ \ / _` / __|/ _ \ ##
## | |___| | (_| | |_| | | |_) | (_| \__ \ __/ ##
## \_____/_|\__, |\__,_|_|_.__/ \__,_|___/\___| ##
## | | ##
## |_| ##
## ##
## Get documentation at docs.liquibase.com ##
## Get certified courses at learn.liquibase.com ##
## Free schema change activity reports at ##
## https://hub.liquibase.com ##
## ##
####################################################
Starting Liquibase at 13:55:46 (version 4.8.0 #1581 built at 2022-02-18 21:43+0000)
Liquibase Version: 4.8.0
Liquibase Community 4.8.0 by Liquibase
Running Changeset: changelog.xml::dw-1042-distributed-trans-error-v2.sql::smcintosh
Unexpected error running Liquibase: MSDTC on server 'SCOTT-MCINTOSH' is unavailable. [Failed SQL: (8501) begin
-- distributed transaction test
print formatmessage('%s START: %s', convert(varchar(20),getdate(),20), convert(varchar(67),@@version));
update RPTDB_XE..OWBTGT.DISTRIB_TRANSACTION_TEST_SCOTT set OBJECT_ID=OBJECT_ID+1;
print formatmessage('%s Updated RPTDB_XE..OWBTGT.DISTRIB_TRANSACTION_TEST_SCOTT: %d rows', convert(varchar(20),getdate(),20), @@rowcount);
insert into dbo.TASK_DETAIL_LOG (BATCH_ID, LOG_DTM, CATEGORY, SEVERITY, ACTION, TASK, SUBTASK, MSG)
values (0,getdate(),'DISTRIB_TRANS','INFO','LIQUIBASE_MIGRATE','PERFORMANCE',null,
'DISTRIB_TRANSACTION_TEST_SCOTT has been updated.');
print formatmessage('%s Inserted dbo.TASK_DETAIL_LOG : %d rows',convert(varchar(20),getdate(),20), @@rowcount);
print formatmessage('%s END', convert(varchar(20),getdate(),20));
end;]
For more information, please use the --log-level flag
The Question :
Why can't Liquibase run this script, when sqlcmd can? In fact, other database tools like TOAD and DataGrip can also successfully run this script, and they too use a JDBC connection, just like Liquibase.
I can see that you're running the sqlFile change type in your changelog. Liquibase has two different modes of operation. The first splits commands on the delimiter (I see you set it to GO) and executes each statement via a JDBC call to the database. However, in your script the commands are not database commands, they are SQLCMD commands. When those statements get executed on the database they will fail.
However, I found this page on the Liquibase docs site that explains the second mode of operation, which is how to run native SQLCMD scripts via Liquibase.
https://docs.liquibase.com/concepts/changelogs/attributes/using-sqlcmd-integration.html
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.