PDO 锁定表行 INNODB

问题描述 投票:0回答:1

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

我的表格有 2 列

id (int) primary
amount (int) index

我想锁定表,但只有一行。

类似的东西

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');

所以这就是我需要做的一切?

php mysql locking innodb
1个回答
1
投票

您显示的示例将导致其他会话执行

SELECT...FOR UPDATE
等待您的 COMMIT。
SELECT...FOR UPDATE
请求的锁是独占锁,因此一次只有一个会话可以获得该锁。因此,如果您的会话持有锁定,其他会话将等待。

您无法阻止非锁定读取。另一个会话可以在没有锁定子句的情况下运行

SELECT
,并且仍然读取数据。但他们无法更新数据,也无法请求锁定读取。

您也可以使用 LOCK TABLES 让每个会话请求表上的锁定,但您说您想要按行级别锁定。

您可以使用 GET_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
进行非锁定读取的客户端。

© www.soinside.com 2019 - 2024. All rights reserved.