スクリプトでデータベースを自動生成するシステムで、CREATE DATABASEはトランザクションが効かないクエリなので例外でrollbackする時自力でrollbackします。その時、防御的措置として、メインのテーブルにレコードが無いものだけを削除できるように以下のように実装しました。
public function dropDatabase()
{
$db = $this->getConnection();
$rec = $db->fetchOne('SELECT id FROM item LIMIT 1');
if($rec)
{
throw new Sdx_Exception("You can't drop database having any item record.");
}
$rootdb = Fc_Db::getRootConnection();
$rootdb->query(sprintf('DROP DATABASE %s', $this->getDatabaseName()));
}
するとデッドロックが発生。SHOW PROCESSLISTで確認すると
Waiting for table metadata lock
とのこと。connectしたDBをそのままドロップすると発生するらしい。
//接続を閉じないとデッドロック
$db->closeConnection();
$rootdb = Fc_Db::getRootConnection();
$rootdb->query(sprintf('DROP DATABASE %s', $this->getDatabaseName()));
}
明示的にconnectを切れば発生しません。MySQL5.5/Autocomit OFFで試しました。