我试图找到一种解决方法,以解决UPDATE和SELECT语句之间的死锁,该死锁很难重现,但发生在生产服务器上。默认情况下,SELECT语句被终止,这是首选。我要处理的方式是:
要模拟死锁,我使用此example。我将第4点修改为:
BEGIN
BEGIN TRY
SELECT 'TRYING TO SELECT 1'
select value, * from B where value = 1 or id = 1
SELECT 'SELECT 1 SUCCESFUL'
END TRY
BEGIN CATCH
SELECT 'TRYING TO SELECT 2'
select value, * from B with (NOLOCK) where value = 1 or id = 1
SELECT 'SELECT 2 SUCCESFUL'
END CATCH
END
我得到的结果是:
我真的不明白为什么看到SELECT 1的结果。但是,如果我用BEGIN TRANSACTION / ROLLBACK包装查询,如下所示:
BEGIN
BEGIN TRANSACTION
BEGIN TRY
SELECT 'TRYING TO SELECT 1'
select value, * from B where value = 1 or id = 1
COMMIT TRANSACTION;
SELECT 'SELECT 1 SUCCESFUL'
END TRY
BEGIN CATCH
IF @@trancount > 0 ROLLBACK TRANSACTION
SELECT 'TRYING TO SELECT 2'
select value, * from B with (NOLOCK) where value = 1 or id = 1
SELECT 'SELECT 2 SUCCESFUL'
END CATCH
END
哪些回滚了挂起的UPDATE事务,这是我不想要的。
如果没有发生死锁,则预期结果是仅执行第一个查询,如果发生死锁,则仅执行第二个查询。
PS。是的,我知道读取未提交的数据可能导致读取不干净和数据不一致。