【问题标题】:SQL Server deadlock when using PreparedStatements使用 PreparedStatements 时的 SQL Server 死锁
【发布时间】:2014-07-23 13:07:40
【问题描述】:

我有一个 java servlet 应用程序,我正在使用准备好的查询来更新 SQL Server 数据库表中的记录。

假设我想执行UPDATE MyTable SET name = 'test' WHERE id = '10'。 (是的,id 是一个 varchar)
我使用以下代码来实现这一点:

PreparedStatement pstmt = con.prepareStatement("UPDATE MyTable SET name = ? WHERE id = ?");
pstmt.setString(1, getName() );
pstmt.setString(2, getID() );
pstmt.executeUpdate();

我发现当我运行 JMeter 脚本来模拟 2 个用户时,这个语句会导致我的数据库出现死锁。

我想检查我在 SQL Profiler 中的值,所以我使用了以下代码,以便检查这些值。

String query = String.format("UPDATE MyTable SET name = '%s' WHERE id = '%s' ", getName(), getID() );
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.executeUpdate();

我的僵局突然消失了!可惜最后一种方法容易受到 SQL 注入的影响。

有没有人可以告诉我发生了什么和/或如何解决它?

【问题讨论】:

  • 死锁到底是什么意思?你是如何确定它是死锁的?
  • 我收到一个 SQLException 说事务已死锁。
  • 你确定是这个改变让死锁消失了吗?我很确定没有办法(不包括不提交事务)运行您上面发布的 SQL 会导致死锁。
  • 您能否始终如一地重现死锁?像@DavidG 一样,我很难理解为什么会发生僵局。
  • 是的,这就是人们正在发生的事情。尝试方法 1 和 2 10 次,10/10 失败/成功。

标签: java sql-server concurrency prepared-statement database-deadlocks


【解决方案1】:

好的,我终于找到了问题并解决了我的问题。

似乎 jTDS JDBC 驱动程序与 MSSQL 的组合是“问题”。

This article 准确地解释了我的情况。在this FAQ 的帮助下,我能够将数据源设置为正确的配置。

据我了解:

如果您的语句使用类似字符串的索引(如我的情况),则表执行索引 SCAN 而不是索引 SEEK。这会导致整个表被锁定并且容易出现死锁。

我希望这对其他人也有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    相关资源
    最近更新 更多