死锁导致部分数据丢失?
partial data loss from deadlock?
我遇到这样一种情况,由于 DB 死锁,我们丢失了部分数据。使用相同的过程将值插入到多个表中,但数据丢失只发生在少数几个表中。这真的可能吗?
默认情况下,交易需要在 SQL 服务器中明确。因此,如果您的程序结构如下:
create procedure dbo.doStuff
as
begin
update table1 …;
update table2 …;
delete table3 …;
insert table4 …;
end
并且您在 table3
删除中遇到死锁,对表 1 和 2 的更新结果应该被认为是持久的(也就是说,它们不会被死锁的回滚所回滚)。如果您需要所有语句以原子方式 succeed/fail ,则需要将整个事物包装在一个事务中。即:
create procedure dbo.doStuff
as
begin
begin transaction;
update table1 …;
update table2 …;
delete table3 …;
insert table4 …;
commit transaction;
end
请记住,这确实对并发性有影响(您持有锁的时间更长)- 不是免费的。而且,虽然你不能依赖它,但它也可以影响哪个进程是死锁受害者(因为部分选择是 "how much work would it be to roll back")!
如果您愿意,您可以(并且可能应该!)使用 begin try
和 xact_state()
变得更高级,但以上是基础知识。
我遇到这样一种情况,由于 DB 死锁,我们丢失了部分数据。使用相同的过程将值插入到多个表中,但数据丢失只发生在少数几个表中。这真的可能吗?
默认情况下,交易需要在 SQL 服务器中明确。因此,如果您的程序结构如下:
create procedure dbo.doStuff
as
begin
update table1 …;
update table2 …;
delete table3 …;
insert table4 …;
end
并且您在 table3
删除中遇到死锁,对表 1 和 2 的更新结果应该被认为是持久的(也就是说,它们不会被死锁的回滚所回滚)。如果您需要所有语句以原子方式 succeed/fail ,则需要将整个事物包装在一个事务中。即:
create procedure dbo.doStuff
as
begin
begin transaction;
update table1 …;
update table2 …;
delete table3 …;
insert table4 …;
commit transaction;
end
请记住,这确实对并发性有影响(您持有锁的时间更长)- 不是免费的。而且,虽然你不能依赖它,但它也可以影响哪个进程是死锁受害者(因为部分选择是 "how much work would it be to roll back")!
如果您愿意,您可以(并且可能应该!)使用 begin try
和 xact_state()
变得更高级,但以上是基础知识。