pdo锁表行innodb

r6hnlfcb  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(248)

我有一个存储敏感数据的表,需要小心,只有一个会话能够读/写特定的行。
我的表有2个列id(int)主数量(int)索引
所以我想把table锁起来,但只有一行

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

im使用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');

所以我只需要这么做?

c7rzv4ha

c7rzv4ha1#

您展示的示例将导致其他会话 SELECT...FOR UPDATE 等待你的承诺。请求的锁 SELECT...FOR UPDATE 是独占锁,因此一次只能有一个会话获取该锁。因此,如果您的会话持有锁,其他会话将等待。
不能阻止非锁定读取。可以运行另一个会话 SELECT 没有锁子句,仍然读取数据。但是他们不能更新数据,也不能请求锁定读取。
您也可以让每个会话请求在带有锁表的表上设置一个锁,但是您说您希望在行范围内设置锁。
您可以使用get\u lock()函数创建自己的自定义锁。这允许您为每个用户id设置一个不同的锁 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() .
但是,您不能阻止要对其执行非锁定读取的客户端 SELECT .

相关问题