我的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语句添加查询提示,谢谢。
暂无答案!
目前还没有任何答案,快来回答吧!