数据库
首页 > 数据库> > mysql-select…中的最新行不可用以进行更新

mysql-select…中的最新行不可用以进行更新

作者:互联网

我在运行正在执行涉及两个表Users和Transactions的事务的Web服务时遇到问题.问题在于,当我从“事务”中选择时,有时无法找到最新行,而我可以看到该行存在于数据库中.

我使用Perl / Dancer作为Web框架,尽管我认为我遇到的问题是数据库级别的(我正在使用MySQL / InnoDB).伪代码如下所示:

my $dbh = DBI->connect_cached(("DBI:mysql:Database;host=localhost;mysql_ssl=1",
                 "user", "password",
                 {RaiseError => 0, AutoCommit => 0});
my $sth_transact = $dbh->prepare("select balance from Users ".
                  "where id=? for update");

... store result in local variable ...

my $sth_inner = $dbh->prepare("select deposit from Transactions ".
                   "where id=?");

$sth_inner->execute();
if (my $deposit = $sth_inner->fetch_row()) {
     $deposit *= $bonus;

     $sth_inner = $dbh->prepare("update Transactions set deposit=?".
                                "where id=?");
     $sth_inner->bind_param(1, $deposit);
     $sth_inner->bind_param(2, $transaction_id);
     $sth_inner->execute();

     ... update balance in Users table ...
}

对于前几个请求,“事务”表上的选择将返回最新行.但是,在第三个请求上,它不再能够找到最新行.当我这样做时:

my $sth_inner = $dbh->prepare("select id from Transactions where id=(SELECT max(id) from Transactions)");

它返回比最新行早3行的ID.例如,如果“交易”表中有87行,则返回84.

我不确定是否处理不正确.我使用select …保护更新更新的用户表,但是我没有使用Transactions表保护它.我不确定这是否重要.由于我将更新嵌套在用于对Users表进行更新的select …中的Transactions表中,因此我认为它将在事务中受到保护.

感谢有关事务表中的选择为何不返回最新行的任何帮助.

解决方法:

此问题通常是由InnoDB的默认隔离级别(“可重复读取”)引起的.这意味着在启动当前事务之后,连接看不到任何添加到数据库的内容.

您可以通过更改隔离级别(可能是Oracle的默认设置为“读取已提交”)或在选择开始新事务之前进行一次提交来避免此问题.

标签:dbi,mysql,perl
来源: https://codeday.me/bug/20191122/2055906.html