PHP - MySQL行级锁定示例

NEW*_*WEB 3 php mysql mysqli innodb rowlocking

我已经看过许多帖子,解释了Select FOR UPDATE的用法以及如何锁定行,但是我无法找到任何解释当代码尝试读取被锁定的行时发生的情况.

例如.假设我使用以下内容:

$con->autocommit(FALSE);
$ps = $con->prepare( "SELECT 1 FROM event WHERE row_id = 100 FOR UPDATE");
$ps->execute();
...
//do something if lock successful
...
$mysqli->commit();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我如何确定我的锁是否成功?行已被锁定时处理场景的最佳方法是什么?

对不起,如果在某处描述,但我似乎找到的只是"快乐路径"的解释.

dog*_*ose 5

在这种情况下,我如何确定我的锁是否成功?行已被锁定时处理场景的最佳方法是什么?

如果你是该行试图锁定已锁定- MySQL服务器将不会返回该行任何回应.它会等待,直到锁定事务被提交或回滚.

(显然:如果已经删除了行,你SELECT将返回一个空的结果集而不是锁定任何东西)

之后,它将返回最新值,由持有锁的事务提交.

常规Select语句不会关心锁定并返回当前值,而忽略了存在未经修改的更改.

因此,换句话说:只有在锁定成功时才会执行您的代码.(其他人等待,直到先前的锁定被释放)

注意,使用FOR UPDATE也将阻止任何事务SELECTS锁定时间 - 如果你不想这样,你应该使用LOCK IN SHARE MODE.这将允许事务选择继续使用当前值,而只是阻止任何更新或删除语句.

²查询将返回错误,在innodb_lock_wait_timeout http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout定义的时间后, 它将返回ERROR 1205(HY000):锁定等待超时超时; 尝试重新启动事务

换句话说:这就是你尝试获取锁定失败的地方.


Sidenode:这种锁定适用于确保数据完整性.(即,在插入引用此行的内容时,不会删除任何引用的行).

一旦锁定被释放,任何被阻止(或更好地调用它被延迟)的删除语句将被执行,可能会删除您刚刚插入Cascading的行,因为您刚刚持有锁定的行以确保完整性.

如果你想创建一个系统来避免2个用户同时修改相同的数据,你应该在应用程序级别执行此操作并查看悲观的 vs 乐观锁定approches,因为保持事务运行很长时间不是一个好主意.一段的时间.(我认为在PHP中,您的数据库连接无论如何都会在每次请求后自动关闭,导致对任何正在运行的事务进行隐式提交)