question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

DML statement locks table in Azure SQL Data Warehouse after implicit transaction.

See original GitHub issue

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 © Microsoft Corporation

Client Operating System

Windows 10 64 bits

JAVA/JVM version

java version “1.8.0_181” Java™ SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot™ 64-Bit Server VM (build 25.181-b13, mixed mode)

Table schema

CREATE TABLE [dbo].[test_lock]
(
	[id] [int] NOT NULL
)
WITH
(
	DISTRIBUTION = ROUND_ROBIN,
	CLUSTERED COLUMNSTORE INDEX
)

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.

  1. Expected behaviour: As long as the connection autoCommit is true, the update statement should not lock the test_lock table.
  2. Actual behaviour: The object Database.dbo.test_lock is locked by the update statement and the deletion cannot be executed.
  3. Error message/stack trace: None
  4. Any other details that can be helpful: 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'
session_id type object_name command acquire_time end_time status state priority
SID00001 Shared Database.sys.sp_executesql exec [sp_executesql] @P1 date date Completed Granted 0
SID00001 ExclusiveUpdate Database.dbo.test_lock UPDATE test_lock SET id = 9 WHERE id = 10 date date Completed Granted 0
SID00002 Shared Database.sys.sp_executesql exec [sp_executesql] @P1 date NULL Running Granted 0
SID00002 ExclusiveUpdate Database.dbo.test_lock DELETE FROM test_lock WHERE id > 8 NULL NULL Suspended Queued 10

JDBC trace logs

Reproduction code

public class Main {
    private static final String INSERT_QUERY = "INSERT INTO test_lock(id) VALUES (10)";
    private static final String UPDATE_QUERY = "UPDATE test_lock SET id = 9 WHERE id =  10";
    private static final String DELETE_QUERY = "DELETE FROM test_lock WHERE id > 8";
    
    private static String driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    private static String jdbcURI = "jdbc:sqlserver://...database=Database";
    private static String user = "";
    private static String password = "";
    
    public static void main(String[] args) {
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (Connection c1 = DriverManager.getConnection(jdbcURI, user, password);
             Connection c2 = DriverManager.getConnection(jdbcURI, user, password);) {
            c1.setAutoCommit(false);
            PreparedStatement ps = c1.prepareStatement(INSERT_QUERY);
            ps.executeUpdate();
            c1.setAutoCommit(true);
            ps = c1.prepareStatement(UPDATE_QUERY);
            ps.executeUpdate();

            PreparedStatement ps2 = c2.prepareStatement(DELETE_QUERY);
            ps2.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
odelpozogcommented, Nov 7, 2018

Hi @peterbae I’ve tested the new driver and it works perfectly. Thank you

1reaction
peterbaecommented, Nov 7, 2018

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:

IF @@TRANCOUNT > 0 COMMIT TRAN set implicit_transactions off 

This works fine for SQL Server, but for Azure DW, between the COMMIT TRAN and set implicit_transaction_off statements, the server will create a new transaction since the implicit transaction was on. This is what’s causing the table to lock, and I think the driver is responsible for cleaning up that transaction.

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!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Transaction locking and row versioning guide - SQL Server
When a connection is operating in implicit transaction mode, the instance of the SQL Server Database Engine automatically starts a new transaction after...
Read more >
SQL Server lock issues when using a DDL (including SELECT ...
In this article, we will explore lock issues with DDL statements, SELECT INTO clause with Common Scenario in Deployment Utilities.
Read more >
Automatic Locks in DML Operations
Table Locks (TM) A transaction automatically acquires a table lock (TM lock) when a table is modified with the following statements: INSERT ,...
Read more >
"lock request time out period exceeded" Error When Trying to ...
In our case, a DML command (view redefinition) was issued againt database using SET IMPLICIT TRANSACTIONS ON without COMMIT TRANSACTION, which accidently caused ......
Read more >
The best ways to use SQL DELETE Statement in a SQL table
By default, SQL Server uses implicit transactions and commits the records without asking the user. As a best practice, you should start an ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found