我这样做是为了确保只有一次这个过程的实例运行(伪代码的PHP/MySQL的InnoDB):MySQL的InnoDB的死锁与排它锁(FOR UPDATE)
START TRANSACTION
$rpid = SELECT `value` FROM locks WHERE name = "lock_name" FOR UPDATE
$pid = posix_getpid();
if($rpid > 0){
$isRunning = posix_kill($rpid, 0);
if(!$isRunning){ // isRunning
INSERT INTO locks values('lock_name', $pid) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)
}else{
ROLLBACK
echo "Allready running...\n";
exit();
}
}else{ // if rpid == 0 -
INSERT INTO locks values('lock_name', $pid) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)
}
COMMIT
...............
//free the pid
INSERT INTO locks values('lock_name', 0) ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)
表锁包含这些字段:
id - primary, autoinc
name - varchar(64) unique key
description - text
value - text
我相信从START TRANSACTIN到COMMIT/ROLLBACK时间真的毫秒 - 没有足够的时间,甚至得到超时。这个代码怎么可能发生死锁?我不在这个交易中使用其他表。看起来死锁是不可能的。如果两个进程同时启动,第一个获得该行锁定的进程将继续,另一个将等待锁定释放。如果锁在1分钟内未释放,则错误为“超时”,而非死锁。
所以,如果我使用UPDATE而不是INSERT,主键就不会受到伤害。此外,问题不在一张桌子上。还有其他表格我无法删除主键。还有其他解决方法吗?当你在一行上进行X锁定时,应该有一种方法来保存地插入一行 – NickSoft 2011-03-28 08:39:22
我想困难的方法是让表锁只有一个唯一索引,并在X锁定和插入更复杂的表之前使用它来锁定。但是这必须在每一个可能发生死锁的插入之前完成,我希望有其他方法。那么是否有另一种方法可以在具有多个(唯一?)索引的表上安全插入。 – NickSoft 2011-03-28 08:44:02