PDO锁定表行INNODB

时间:2018-07-20 13:08:28

标签: php mysql locking innodb

我有一张存储敏感数据的表,需要注意,只有一个会话能够在特定行上进行读取/写入。

我的桌子上有2列 id(int)主要 金额(整数)索引

所以我想锁定表但只有一行 像

LOCK TABLEROWS `mytable` WRITE WHERE `id` = 1

使用pdo和startTransaction的即时消息不会阻止其他会话在此时间内进行读写

我阅读了InnoDB文档,但没有让它运行

编辑:

$_PDO->exec('START TRANSACTION');
$_PDO->query('SELECT * FROM `currency` WHERE `id` = '.$userid.' FOR UPDATE');  
//maybe do update or not check if
$_PDO->exec('COMMIT');

那就是我需要做的吗?

1 个答案:

答案 0 :(得分:1)

您显示的示例将导致其他进行window.addEventListener("scroll")的会话等待COMMIT。 SELECT...FOR UPDATE请求的锁是排他的锁,因此一次只能有一个会话获得该锁。因此,如果您的会话持有该锁,则其他会话将等待。

您不能阻止非锁定读取。另一个会话可以在没有锁定子句的情况下运行SELECT...FOR UPDATE,并且仍然可以读取数据。但是他们无法更新数据,也无法请求锁定读取。

您也可以使用LOCK TABLES使每个会话请求在表上锁定,但是您说要在行标度上锁定。

您可以使用GET_LOCK()函数创建自己的自定义锁。这使您可以为每个用户ID设置一个独特的锁。如果对访问表的所有代码都执行此操作,则无需使用SELECT

FOR UPDATE

这取决于所有客户端代码的配合。他们都需要在处理给定行之前获取锁。您可以使用$lockName = 'currency' . (int) $userid; $_PDO->beginTransaction(); $stmt = $_PDO->prepare("SELECT GET_LOCK(?, -1)"); $stmt->execute([$lockName]); $stmt = $_PDO->prepare('SELECT * FROM `currency` WHERE `id` = ?'); $stmt->execute([$userid]); //maybe do update or not check if $_PDO->commit(); $stmt = $_PDO->prepare("SELECT RELEASE_LOCK(?)"); $stmt->execute([$lockName]); ,也可以使用SELECT...FOR UPDATE

但是您不能阻止要使用GET_LOCK()进行非锁定读取的客户端。