简体   繁体   English

MySQL 和 PHP:使用 SELECT FOR UPDATE

[英]MySQL and PHP: Using SELECT FOR UPDATE

I am trying to acquire a row-level lock for a table in a database that prevents any future sessions from reading that row until the lock is released.我正在尝试为数据库中的表获取行级锁,以防止任何未来的会话在锁被释放之前读取该行。

To accomplish this, I've been trying to use the SELECT ... FOR UPDATE syntax on an indexed column, but I can't seem to prevent other sessions from reading that row when they use the exact same query.为了实现这一点,我一直在尝试在索引列上使用SELECT ... FOR UPDATE语法,但我似乎无法阻止其他会话在使用完全相同的查询时读取该行。

Is there something more I need to do?还有什么我需要做的吗? I'm using MySQL 5.5, PHP 7, and the table in question is Innodb.我使用的是 MySQL 5.5、PHP 7,有问题的表是 Innodb。

To elaborate, the flow is thus:详细地说,流程是这样的:

START TRANSACTION;
SELECT id FROM tbl WHERE id = 1 FOR UPDATE;
... (PHP stuffs)
UPDATE tbl SET value = 'xyz' WHERE id = 1;
COMMIT TRANSACTION;

Subsequent requests will also run the exact same lines of code, but I would like one request to block the others from starting until it's committed the transaction.后续请求也将运行完全相同的代码行,但我希望一个请求在提交事务之前阻止其他请求开始。

Have you looked in the MySql docs about the InnoDB lock types?您是否查看过有关 InnoDB 锁类型的 MySql 文档?

https://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html https://dev.mysql.com/doc/refman/5.5/en/innodb-locking.html

For some unknown reasons I could not get the SELECT FOR UPDATE to work well with my codes (still trying though) but meanwhile, I had to implement my own lock on an innoDB table.由于一些未知的原因,我无法让 SELECT FOR UPDATE 与我的代码一起工作(尽管仍在尝试)但与此同时,我必须在 innoDB 表上实现我自己的锁。 The issue was avoidance of transaction balances mix-ups for a payment gateway I am developing.问题是避免我正在开发的支付网关的交易余额混淆。 The following pseudo code can help anyone looking for an alternative transaction locks .以下伪代码可以帮助任何寻找替代事务锁的人

//Add transaction lock flag column into your table
//TXN_LOCK; Defaulted to Integer 0;

//FIRST: Select the balance and current txn-lock value  
$stopCount = 1;
$dbBalance = $tnxLock = 0;
$failureFlag = false; 
do {
    //run the select query; get values including $dbBalance and $tnxLock 
    //increment the counter; we won't run this forever          
    $stopCount++;
    if($stopCount > 3){
        //only a few trials
        $failureFlag = true;
        break;
    }
    //lock table, it looks free
    if($tnxLock == '0'){
        //update table set tnxLock = 1;         
    }
}while ($tnxLock > 0);  

if($failureFlag){
    //log and end; return failure   
    return false;
}else {
    //proceed 
}   
//--------------------------------

//now do you mathematics 
//add or subtract value from the balance

//then update the table; at the same time update the lock-code back to zero 
//UPDATE table set balance = xxx, tnxLock = 0;

//NOTE: This can be set as a function, 
//   with right params and flags of doing both credits and debits and 
//   called each time such operation is needed for consistency
//   Normal begin and commit transaction can also be added for more stability

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM