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の公式サイトに記載がありました。

上記サイトの一部を引用

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メソッドを使うように調整します。

最後に

ちょっとしたことでしたが、

調査に戸惑ったので、個人的なメモです。

上記、少しでも参考になれば幸いです。

就職/転職に向けてスキルを高めるために

プログラミングのスキルを高めるために、

以下のサイトを参考にしてみてください。

おすすめ書籍

コメント一覧

コメントはまだありません。

コメント送信

コメントを残す

広告

おすすめ記事