概要
laravelのとあるDBのデータ削除処理にてdelete()
だとエラーは出ず、truncate()
だとエラーが出るので原因を調査してみた。
前提
DBはMySQL
エラーが出る状態のコードを下記に記載する。
トランケート対象テーブル名はhogesでモデルクラス名はHogeである。
hogesテーブルに外部キー制約は無い。
トランケートを選んだ理由は「パフォーマンス良い」「中身が消せればいい」程度。
try {
DB::beginTransaction();
// その他の処理
Hoge::truncate();
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
上記の処理を実行すると下記のエラーがでる。
There is no active transaction (意訳:「アクティブなトランザクションが無い」)
解消方法
下記の様にtruncate()
ではなくdelete()
を利用する。
try {
DB::beginTransaction();
// その他の処理
Hoge::query()->delete;
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
もしくはトランザクションを使わずtruncate()
を利用する。
エラーの原因
下記の記事でまとめたようにtruncate()
はSQLのTRUNCATE TABLE
句を実行している。
そしてMySQLの場合のTRUNCATE TABLE
句は内部で暗黙的にトランザクションとコミットを行っておりロールバック非対応だ。
あくまで予想であるが今回自身が意図定期にtry catchの中でDB::beginTransaction();
を宣言しトランザクションを開いたが、truncate()
が実行したTRUNCATE TABLE
句によってこのトランザクションが閉じられ、DB::commit();
で閉じるトランザクションが見当たらなかったのではないか。
実際にlaravelのエラー画面でもDB::commit();
でエラーが出ていることがわかる。
参考文献