我有一张存储敏感数据的表,需要注意,只有一个会话能够在特定行上进行读取/写入。
我的桌子上有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');
那就是我需要做的吗?
答案 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()
进行非锁定读取的客户端。