2021/04/03

正しい対処法 Issuing rollback() due to DESTROY without explicit disconnect()

[perl] [DBI]

この Issuing rollback() due to DESTROY without explicit disconnect() という警告を発しているのが DBI か DBD かまでは追ってないけど、掲題の通り Perl で MySQL にアクセスしていると「Issuing rollback() due to DESTROY without explicit disconnect()」という Warning に出会うことがある。

この warn は何か

Issuing rollback() due to DESTROY without explicit disconnect()

これは DBIAutoCommit オプションを 0 にしていると起こることがある。0 の意味は「AutoCommitしない」、つまり自分でトランザクションを管理します、ということになる。

で、この「Issuing rollback() due to DESTROY without explicit disconnect()」というエラーを google で検索すると、AutoCommitをオンにするか、Warnオプションで出力させなくするか、selectしただけのときも commit/rollback するという対処法が上位にでてくるが、どれもあまり適切ではない。

そもそも AutoCommit の設定をひっくり返せるならともかく、AutoCommit:0 にしている人は、そうしたくてしているわけなので、通常 AutoCommit を 1 にするという対応は難しい。また、Warnオプションを使ってWarnを抑制するのは、その他のWarnまで止めてしまう可能性があるのでやめた方が良い。また、updateしないでselectした時にも commit/rollback するというのは、副作用という意味ではあまり他に影響することはなさそうだが、トランザクションがネストするようなとき、意図しないタイミングで commit/rollback してしまうことがあるかもしれないので避けた方が良さそうだし、selectしかしていないのにそもそも毎度commit/rollbackなんて面倒くさくてやってられないですよね。

正しい対処法

というわけで、このwarnは、AutoCommit の設定によって発生するのと、エラーメッセージの先頭に Issuing rollback() rollbackしたと書いているので、commit/rollbackすることに意識が向きがちだけど、エラーメッセージをちゃんと読むと以下のように書いてあって

due to DESTROY without explicit disconnect()

明示的に disconnect されないまま DBI/DBD オブジェクトが DESTROY されたよってことなのです。

つまり対処法としては、DBI/DBD オブジェクトが破棄される前に、ちゃんと disconnect せよ、ということになります。AutoCommit:0 を宣言して、トランザクションを利用するわけですから、接続と切断まできちんとハンドリングしないとダメだよ、という警告なわけです。というわけで、オブジェクトの破棄に任せて切断するのではなく、ちゃんと明示的に disconnect してあげれば警告はでなくなりますし、selectだけしたあとに commit/rollback はまったく必要ありません。

おわり。

サイト内検索