ドゥアイネットのプログラマー、湯川が開発日記を綴ります。

CALENDAR
S M T W T F S
  12345
6789101112
13141516171819
20212223242526
2728293031  
<< January 2019 >>
ARCHIVES
CATEGORIES
<< 上下キーイベント | main | MySQLのインデックスのファイルサイズ >>
MySQLでLock wait timeout exceededエラー

以前からMySQLで「Lock wait timeout exceeded; try restarting transaction」エラーが発生していました。

原因がよくわからなかったのですが、ロックをかける際にテーブルロックとレコードロックを同時に実行するとデッドロックに陥るようです。

以下のようなサンプルをコンソールから同時に実行すると片方が止まります。
テーブルタイプがInnoDBの場合は、レコードロックのみでロックするのがよさそうです。

<?php
//レコードロックでロックする
$db = mysql_connect('192.168.1.xx', 'xxxxx', 'xxxxx');
mysql_select_db('test', $db);
for ($i=0; $i<1000; $i++) {
  mysql_query('begin');
  $rs = mysql_query("select b from test where a = 'AAA' for update");
  $row = mysql_fetch_assoc($rs);
  $num = $row['b'];
  $nextnum = $num + 1;
  mysql_query("update test set b = '$nextnum' where a = 'AAA'");
  mysql_query('commit');
  print("b=[" . $num . "]¥n");
}
?>

<?php
//テーブルロックでロックする
$db = mysql_connect('192.168.1.xx', 'xxxxx', 'xxxxx');
mysql_select_db('test', $db);
for ($i=0; $i<1000; $i++) {
  mysql_query('lock tables test write');
  $rs = mysql_query("select b from test where a = 'AAA'");
  $row = mysql_fetch_assoc($rs);
  $num = $row['b'];
  $nextnum = $num + 1;
  mysql_query("update test set b = '$nextnum' where a = 'AAA'");
  mysql_query('unlock tables');
  print("b=[" . $num . "]¥n");
}
?>

| Mysql | 17:59 | comments(0) | - |
コメント
コメントする