我在访问MySQL数据库的两个应用程序中使用了UniDAC (Devart)。在一个应用程序执行一些繁重的更新更新操作期间,我偶尔会在另一个应用程序中收到错误消息"#40001 Deadlock found when restarting“。在阅读了MySQL应对此问题的提示后,他们建议重试事务。我的问题是知道在Delphi中做这件事的最好方法。我正在做这个:
transaction_completed_ok:= False;
repeat
try
my_db.StartTransaction;
(... do the inserts)
my_db.Commit;
transaction_completed_ok:= True;
except
my_db.Rollback;
Sleep(1000);
end;
until transaction_completed_ok;在两个应用程序上对每个事务执行此操作,是处理问题的有效方法吗?有人能分享一个最好的方法吗?欢迎任何帮助。
发布于 2013-07-25 20:51:02
您用于在出错时重新启动事务的代码无法解决问题,因为重新执行一个相同的代码将导致相同的错误。例如,如果您的代码导致唯一性冲突,应用程序将被卡住。为了解决这个问题,您应该重新组织应用程序逻辑,以避免死锁。当两个并行连接试图以不同的顺序锁定两个表时,就会发生死锁,例如:
connection1 locks tableA;
connection2 locks tableB;
connection1 attempts to lock tableB - waits for connection2 to unlock tableB;
connection2 attempts to lock tableA - waits for connection1 to unlock tableA.结果,我们得到了一个死锁。为了避免死锁,您应该为两个连接设置相同的表锁定顺序,例如:
connection1 locks tableA;
connection2 locks tableA;
connection1 locks tableB;
connection2 locks tableB.您可以在http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html上阅读有关死锁的更多信息
要解决此问题,您可以使用以下算法:
isLocked := False;
while not isLocked do
try
< explicit lock tableA >
< explicit lock tableB >
isLocked := True;
except
< explicit unlock tableA >
< explicit unlock tableB >
end;
if isLocked then
try
< do inserting to tableA and tableB >
finally
< explicit unlock tableA >
< explicit unlock tableB >
end;https://stackoverflow.com/questions/17843982
复制相似问题