-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DML statement locks table in Azure SQL Data Warehouse after implicit transaction. #872
Comments
Hi @odelpozog, thanks for reporting this issue. I was able to reproduce the issue, but I'm trying to pin down why this problem is occurring. I see that the repro code works fine with SQL Server, and it's only locking to table in Azure DW - I'll let you know as soon as I have an update on this issue. |
Hi @odelpozog, I've looked into this issue a bit deeper, and it seems like this is not a JDBC driver issue, nor an issue with Azure DW - I believe this is the intended behavior. First of all, I confirmed that this is not our driver's issue by performing the same actions (from your repro code) in Azure DW. I first ran this query in one Query Editor in the Azure portal:
While the while loop is keeping this connection open, I ran this query in another Query Editor:
Which showed that a lock was still on the test_lock table. Since this operation doesn't use our JDBC driver, it showed that this was not our driver's issue. Afterwards, I found this part of the MSDN document from here:
I could confirm this behavior by putting queries that SELECT @@TRANCOUNT, and saw that a transaction was always active when we had the implicit transaction mode ON. This is why the lock was placed on the test_lock table in your repro code - because by the time you call To demonstrate this behavior, I provided a modified version of the code I provided previously below. This will correctly close the transaction (that Azure DW opens for us every time when implicit transaction mode is ON) before we run the update statement in implicit transaction mode OFF, and the test_lock table won't be locked during the while loop:
I also confirmed that a Java version of the code I provided above works correctly (you'll have to execute COMMIT TRANS from a statement instead of calling c1.commit() after you set c1.setAutoCommit(true), since the JDBC API suggests that commit() should not be called when autocommit is set to true, so that c1.commit() will end up becoming a no-op). I hope this answers your question. Please let me know if you had other concerns/questions. |
Hi @peterbae , thank for your reply. I have tested your suggestion about executing COMMIT TRANS after setting the auto-commit property to true and it almost works (it raises the exception 112006;Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.). Anyway, it indeed decreases the @@TRANCOUNT. Executing my original java code again, I do think there is an issue with Azure SQL DW.
The correspondence between the java statements and the Azure SQLDW statements seem correct, the auto-commit to true executes the COMMIT TRANS and it restores the value of implicit_transactions to off. But, the TRANCOUNT counter is still 1 after that. According the JDBC setAutoCommit documentation:
IMHO with setAutoCommit(true) the current transaction has to be committed and the next executed statements have to be committed automatically, without locking any database object (TRANCOUNT should have been decreased to 0). If I need to execute a COMMIT TRAN statement after the setAutoCommit(true) my code will depend on the specific database being used, losing the benefits of using JDBC interfaces. Looking forward to your comments, regards. |
I think that's a good point. The problem right now is in SQLServerConnection::setAutoCommit - when setAutoCommit is called, currently we execute this command when we want to turn off implicit transaction:
This works fine for SQL Server, but for Azure DW, between the I swapped the order of those two statements (it shouldn't affect anything other than closing the new transaction in DW), and it seems to work fine. I've created a Java 8 version of the newest driver that contains the change and I've attached it to this comment. Please give this jar a try and see if it now behaves the way you expect it to: mssql-jdbc-7.1.3-github872.jre8-preview.jar.zip If the jar works well for you and after further internal testing, I will create a PR that swaps the order of those two statements. Please let me know! |
Hi @peterbae |
Hi @peterbae When is this fix expected to be part of an official release? |
This fix is expected to be part of the next preview release, which is scheduled for the end of this month. |
Closing Issue as PR #881 merged. |
Driver version
6.2.2.jre8, 6.4.0.jre8, 7.1.2.jre8-preview
SQL Server version
Microsoft Azure SQL Data Warehouse - 10.0.9999.0
Oct 10 2018 00:19:18
Copyright (c) Microsoft Corporation
Client Operating System
Windows 10 64 bits
JAVA/JVM version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
Table schema
Problem description
Executing a DML statement after an implicit transaction locks the affected table. Locks are released when the connection is closed but if the connection is in a pool, it would not be closed being used.
As long as the connection autoCommit is true, the update statement should not lock the test_lock table.
The object Database.dbo.test_lock is locked by the update statement and the deletion cannot be executed.
None
Executing the query after the lock I get the following results:
SELECT TOP ,l.[session_id] ,l.[type] ,l.[object_name] , r.[command] ,l.[acquire_time] ,r.[end_time] ,r.[status] ,l.[state] ,l.[priority] FROM [sys].[dm_pdw_lock_waits] l inner join [sys].[dm_pdw_exec_requests] r on l.request_id = r.request_id where l.[object_type] = 'OBJECT'
JDBC trace logs
Reproduction code
The text was updated successfully, but these errors were encountered: