我這樣做是爲了確保只有一次這個過程的實例運行(僞代碼的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