Track non-deterministic MySQL errors in Perl

若如初见. 提交于 2019-12-13 13:31:04

问题


I have a single-thread Perl script running on a hosted shared server that mainly executes the following code:

my $O_dbh = DBI->connect("dbi:mysql:dbname=dbname", "abc", "xxx", {RaiseError => 1});
$O_dbh->begin_work();

my $O_sth1 = $O_dbh->prepare('SELECT COUNT(*) FROM mytable WHERE any = 5');

$O_sth1->execute();
my @result1 = $O_sth1->fetchrow_array();
my $oldValue = $result1[0];

$O_sth1->finish();

my $O_sth2 = $O_dbh->prepare('INSERT INTO mytable (any) VALUES (5)');
$O_sth2->execute();

$O_sth1->execute();
my @result2 = $O_sth1->fetchrow_array();
my $newValue = $result2[0];

if ($oldValue + 1 == $newValue) {
  $O_dbh->commit();
} 
else {
  $O_dbh->rollback();
  die "why?! new = $newValue, old = $oldValue";
}

Some times (<1%) the code runs into the rollback case and fails. On my local system I cannot reproduce this error. The database is MySQL 5.

CREATE TABLE `mytable` (
  `id` int(11) NOT NULL auto_increment,
  `any` int(11) NOT NULL default '1',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

How can I track down this error? Any help would be greatly appreciated.


回答1:


Assuming your database is running with the default settings, I am more surprised that your SELECT ever returns two different values.

The documentation says this

If the transaction isolation level is REPEATABLE READ (the default level), all consistent reads within the same transaction read the snapshot established by the first such read in that transaction. You can get a fresher snapshot for your queries by committing the current transaction and after that issuing new queries.

So, if the default REPEATABLE READ isolation level is in effect, I would expect that all queries would return data consistent with the state of the database at the moment of the first query.

However, it does sound like this may help

With READ COMMITTED isolation level, each consistent read within a transaction sets and reads its own fresh snapshot.

I think you should try

$O_dbh->do('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED');

immediately after the connect, and see if that fixes things for you.

However, you should make sure to either disconnect the database handle after this transaction or return it to the previous isolation level. Otherwise you will start to get inconsistent results.



来源:https://stackoverflow.com/questions/17248553/track-non-deterministic-mysql-errors-in-perl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!