LaravelのORMでのトランザクションで「There is no active transaction」のエラーになった件
Laravelを使用していて、
ORMを使って処理を構築していたとき、
トランザクション周りで、
There is no active transaction
のエラーが発生したが、
この件、なぜか調べたときの内容。
個人的にメモ。
Laravelのバージョン
Laravelのバージョンとしては、
php artisan --version
というコマンドで確認すると、
$ php artisan --version
Laravel Framework 10.48.10
というバージョンであることがわかります。
事象
自分の方で、
エクスポート処理を作成しており、
DB::beginTransaction();
他の箇所で同じような処理自体は挙動は問題ない。
ただし、
新しく作成した処理では、
There is no active transaction
というエラーが起きていた。
原因
今回、自分の処理コードで発生した事象は、
原因としては、
DB::table('sample_table')->truncate();
を実行していると、
コミットが発生していることが原因でした。
DB::beginTransaction();
DB::table('sample_table')->truncate();
DB::commit();
という処理が、
truncateを実行すると、コミットが発生していることで、
その後のコミットで、
There is no active transaction
が発生していたということ。
この件は、
Laravelのtruncateの仕様だが、元を辿ると、MySQLのtruncateの仕様
という点を理解すべきですね。
以下のMySQLの公式サイトに記載がありました。
https://dev.mysql.com/doc/refman/8.0/en/truncate-table.html
上記サイトの一部を引用
Truncate operations cause an implicit commit, and so cannot be rolled back.
切り捨て操作は暗黙のコミットを引き起こすため、ロールバックすることはできない。(DeepL翻訳)
ということなので注意が必要ですね。
対策
対策としては、
- トランザクションの開始、終了の中に入れない
- truncateメソッドではなく、deleteメソッドを使用する
という対応を行う必要があります。
トランザクションの開始、終了の中に入れない
コミットが暗黙的に発生するので、
トランザクションの範囲から外します。
DB::beginTransaction();
DB::table('sample_table')->truncate();
DB::commit();
のコードを、
DB::table('sample_table')->truncate();
DB::beginTransaction();
DB::commit();
にする形ですね。
truncateメソッドではなく、deleteメソッドを使用する
暗黙的なコミットが、
truncateでは発生しますが、
deleteでは暗黙的なコミットは発生しない
という点を考え、
deleteメソッドを使用します。
DB::beginTransaction();
DB::table('sample_table')->truncate();
DB::commit();
というコードを、
DB::beginTransaction();
DB::table('sample_table')->delete();
DB::commit();
という形で、
deleteメソッドを使うように調整します。
最後に
ちょっとしたことでしたが、
調査に戸惑ったので、個人的なメモです。
上記、少しでも参考になれば幸いです。
就職/転職に向けてスキルを高めるために
プログラミングのスキルを高めるために、
以下のサイトを参考にしてみてください。
おすすめ書籍
コメント一覧
コメントはまだありません。
コメントを残す