PDO 锁定 Table 行 INNODB
PDO Lock Table Row INNODB
我有一个 table 存储敏感数据的地方,需要小心,只有一个会话能够 read/write 在特定行上。
我的 table 有 2 列
id (int) 主要
金额(整数)指数
所以我想锁定 table 但只有一行
像
LOCK TABLEROWS `mytable` WRITE WHERE `id` = 1
我使用 pdo 和 startTransaction 不会阻止其他会话到 read/write 由于那个时间
我阅读了 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');
这就是我需要做的吗?
您显示的示例将导致其他正在执行 SELECT...FOR UPDATE
的会话等待您的 COMMIT。 SELECT...FOR UPDATE
请求的锁是独占锁,所以一次只有一个session可以获得锁。因此,如果您的会话持有锁,其他会话将等待。
您不能阻止非锁定读取。另一个会话可以 运行 SELECT
没有锁定子句,并且仍然读取数据。但是他们不能更新数据,也不能请求锁定读取。
您也可以使用 LOCK TABLES 使每个会话请求在 table 上锁定,但您说您想要在行规模上锁定。
您可以使用 GET_LOCK() 功能创建自己的自定义锁。这允许您为每个用户 ID 设置不同的锁。如果对访问 table 的所有代码执行此操作,则不需要使用 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
进行非锁定读取的客户端。
我有一个 table 存储敏感数据的地方,需要小心,只有一个会话能够 read/write 在特定行上。
我的 table 有 2 列 id (int) 主要 金额(整数)指数
所以我想锁定 table 但只有一行 像
LOCK TABLEROWS `mytable` WRITE WHERE `id` = 1
我使用 pdo 和 startTransaction 不会阻止其他会话到 read/write 由于那个时间
我阅读了 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');
这就是我需要做的吗?
您显示的示例将导致其他正在执行 SELECT...FOR UPDATE
的会话等待您的 COMMIT。 SELECT...FOR UPDATE
请求的锁是独占锁,所以一次只有一个session可以获得锁。因此,如果您的会话持有锁,其他会话将等待。
您不能阻止非锁定读取。另一个会话可以 运行 SELECT
没有锁定子句,并且仍然读取数据。但是他们不能更新数据,也不能请求锁定读取。
您也可以使用 LOCK TABLES 使每个会话请求在 table 上锁定,但您说您想要在行规模上锁定。
您可以使用 GET_LOCK() 功能创建自己的自定义锁。这允许您为每个用户 ID 设置不同的锁。如果对访问 table 的所有代码执行此操作,则不需要使用 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
进行非锁定读取的客户端。