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