我使用自己的PHP函数来锁定一些脚本和MySQL表数据,以避免脚本多次运行时多次修改或插入数据。
功能很简单,只需将 MySQL 行从 0 更新为 1,准备好后将 1 更新为 0。
我的脚本总是在开始时检查这个值,如果它是 1,它就会等待,或者退出(这取决于情况)。
这个方法就像一个魅力,除了一种情况:如果两个脚本恰好在同一时间启动,它会比其他查询晚更新该行,但它仍然返回 0,因此它们执行两次工作,这会导致数据库不一致。这种情况很少发生,但那一次却引起了巨大的骚动。
我使用这个解决方案而不是flock(),因为我还必须独立于PHP脚本来保护MySQL表。
我该怎么办? TIA
我的两个主要功能:
function check( $menu ){
global $Db;
$lock = mysqli_query( $Db, "SELECT COUNT(*) AS c FROM lock WHERE $menu='1' AND date >= NOW() - INTERVAL 12 SECOND;" );
$lockData = mysqli_fetch_object( $lock );
mysqli_free_result( $lock );
if ( $lockData->c > 0 ) return true; else return false;
}
function lock( $menu, $state ){
global $Db;
if ( $state == '1' ) $query = "UPDATE lock SET $menu='$state', date=NOW()"; else $query = "UPDATE lock SET $menu='$state'";
mysqli_query( $Db, $query );
}
不要使用MySQL的“事务”来锁定超过几秒钟。它不是为此而设计的,并且可能会导致严重的挂起。 (是的,对于短案例来说,FOR UPDATE
可能是必要的。)
GET_LOCK()
及其朋友是 MySQL 中更简单的替代方案。最有效的是使用文件系统锁。请务必将其放在
/tmp
中,以便在崩溃后它会自动消失。