【问题标题】:PDO Lock Table Row INNODBPDO 锁定表行 INNODB
【发布时间】:2018-07-20 13:08:27
【问题描述】:

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

我的表有 2 个列 id (int) 主要 数量(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');

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

【问题讨论】:

标签: php mysql locking innodb


【解决方案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 进行非锁定读取的客户端。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    • 1970-01-01
    相关资源
    最近更新 更多