更新主键

时间:2016-03-31 11:12:13

标签: sql sql-server database sql-server-2012 deadlock

我遇到了一个奇怪的问题,我不确定如何正确解决它。我有一个表被击中很多,并开始产生死锁。

我的表格如下:

CREATE TABLE object 
(
            id NVARCHAR(255) NOT NULL,
            type NVARCHAR(255) NOT NULL,
            subId NVARCHAR(255) NOT NULL,
            scheduleTime BIGINT NOT NULL,
            message NVARCHAR(MAX),
            status TINYINT,
            send_to NVARCHAR(255),
            owner NVARCHAR(255),
            date DATETIME,
            retry TINYINT,
            CONSTRAINT pk PRIMARY KEY(id, type, subId, scheduleTime, send_to)
);

冲突的两个查询是声明查询和一个发布查询的一个更新。

所以我的工作人员这样做:

  1. 使用正确的所有者
  2. 更新前X行
  3. 选择现在拥有正确所有者的行
  4. 根据键
  5. 释放行

    查询A:

    UPDATE TOP (?) object 
    SET owner = ?, status = 2 
    WHERE owner IS NULL 
      AND send_date <= ? 
      AND status = 1
    

    查询B:

    UPDATE object 
    SET status = %s, 
        owner = NULL, 
        retry = retry + 1 
    WHERE ( (%s) AND owner='%s');
    

    简而言之,查询A:

    • 更新X行并更改状态+设置所有者所有者为NULL且状态为1
    • 的所有者

    查询B:

    • 将所有行设置状态更新为&gt; 2,owner为null,其中owner为NOT NULL且状态为2。

    我的问题:

    这2个查询如何死锁?它们在设计上是否可以同时在同一行上运行?他们不应该互相僵持。

    更多信息:

    从我的死锁图中,我可以看到SQLServer正在取出一个PageLock。 从现有的死锁中我可以看出,查询被杀死并回滚是随机的。

    我正在使用SQL Server 2012和Microsoft 4.2 JDBC驱动程序

    我的问题:

    1. 我该如何解决这个问题?我有两个想法:
    2. 1.1。更改查询A以预先进行选择,然后使用主键来更新它们。 1.2。更改查询以专门取出Rowlock。

      将锁更改为行锁是否有问题?我会遇到任何风险/性能问题?

      1. 在应用程序层添加重试逻辑。 我可以捕获异常并重试直到它通过。不理想,因为它有点杀戮性能。

      2. 将隔离级别更改为READ_UNCOMMITTED 由于我的设计查询永远无法处理相同的数据,因此将隔离级别设置为不可以吗?

      3. 对此的任何帮助都会很棒。我仍然在努力了解这是如何以及为什么会发生这种情况,这使得很难为它制定计划。

        谢谢,

        阿图尔

0 个答案:

没有答案
相关问题