【问题标题】:PHP - MySQL Row level locking examplePHP - MySQL 行级锁定示例
【发布时间】:2014-10-29 16:50:47
【问题描述】:

我看过许多解释 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();

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

很抱歉,如果这在某处有所描述,但我似乎只能找到“快乐之路”的解释。

【问题讨论】:

  • 通常 SELECT 是非锁定的,因为它们是非事务性的读取操作。
  • 如果它被锁定以供阅读,它会等待。并等待。 (取决于您的SESSION TRANSACTION ISOLATION LEVEL)。但通常你会看到“陈旧”的数据(即:尚未提交的事务中还没有数据,因此“陈旧”是有争议的),而不是在读取时遇到行锁定。
  • 它还取决于表类型。我假设这是InnoDB?
  • 是的,数据库是 InnoDB
  • 所以你在说@Wrikken - 我的代码应该假设成功锁定并继续执行逻辑 - 以便并发事务看起来类似于之前完成的事务。基本上,如果事务 1 锁定并在事务 2 尝试读取时进行更改,那么事务 2 会以与事务 1 非并发发生但在 T2 的读取时间之前发生的方式相同。

标签: php mysql mysqli innodb rowlocking


【解决方案1】:

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

如果您尝试锁定的行已锁定 - mysql 服务器不会针对该行返回任何响应。它将等待²,直到锁定事务被提交或回滚。

(显然:如果该行已被删除,您的SELECT 将返回一个空结果集并且不锁定任何内容)

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

常规Select 语句将不关心锁并返回当前 值,忽略存在未提交的更改。

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

注意,使用FOR UPDATE 也会阻塞任何事务性SELECTS,因为你不想要这个,你应该使用LOCK IN SHARE MODE。这将允许事务选择继续使用 current 值,同时阻止任何更新或删除语句。

² 查询将在innodb_lock_wait_timeout http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout 定义的时间之后返回错误 然后它将返回 ERROR 1205 (HY000): Lock wait timeout exceeded;尝试重启事务

换句话说:这就是您尝试获取锁失败的地方。


Sidenode:这种锁定只是适合确保数据完整性。 (即,当您插入引用该行的内容时,不会删除任何引用的行)。

一旦锁被释放,任何阻塞(或者更好地称之为延迟)删除语句都会被执行,可能会删除你刚刚插入的行,因为Cascading在你刚刚持有的行上锁以确保完整性。

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

【讨论】:

  • 反应很好。我昨天阅读了 Wrikkn 的回复,我很困惑,因为他提到使用 FOR UPDATE 时仍然会发生 SELECTS。我知道在某些情况下使用 WHERE 子句如何使您受益,但是您必须始终了解可能对您正在使用的数据进行的所有不同类型的更新,以确保它们都封装在您的更新语句中。我不想这样做,因为有很多方法可以更新我正在查看的数据。我只想暂时“锁定” 2 或 3 个表中的几行,以便更新它们,然后释放。
猜你喜欢
  • 1970-01-01
  • 2017-02-01
  • 2012-04-06
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-23
相关资源
最近更新 更多