sql server 2012在update语句中不使用专门创建的非聚集索引,并导致死锁

gv8xihay  于 2021-07-24  发布在  Java
关注(0)|答案(0)|浏览(212)

我的java程序同时执行以下参数化语句(表名和列名已更改)。

insert into t_test (a,b,c) values (@param1, @param2, @param3)
update t_test set a=@param1 where id=@param2
update t_test set a=@param1 where a=@param2 and b=@param3 and c=@param4

表结构是

CREATE TABLE t_test (
    [id]            [bigint] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [a]             [int] NULL,
    [b]             [int] NULL,
    [c]             [int] NULL
);

并专门为此查询创建索引:

CREATE NONCLUSTERED INDEX [i_test] ON [t_test] (a,b,c);

我从查询计划中发现,当表的大小小于~3000行时,数据库通过聚集索引扫描选择要更新的行;当表的大小增长到超过3000行之后,数据库开始使用i d u测试。
问题是,如果数据库使用聚集索引扫描,它将尝试在t\u test的每一行上获取一个u锁,这在并发执行时会导致死锁。
实际查询类似于:
交易a:

insert into t_test (a,b,c) values (1, 1, 0)
-- say the id inserted is 1
update t_test set a=1 where id=1
update t_test set a=1 where a=1 and b=2 and c=0 --Deadlock

交易b:

insert into t_test (a,b,c) values (1, 2, 0)
-- say the id inserted is 2
update t_test set a=1 where id=2
update t_test set a=1 where a=1 and b=2 and c=0  --Deadlock

通过在ssms中执行直接sql,可以重现这种现象。
请告诉我是否有一个很好的解决方案来强制数据库使用i\u test而不向update语句添加查询提示,谢谢。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题