節子、それInnoDBやない!!MyISAMや!!トランザクション周りではまったたった一つの原因
MyISAMはトランザクションサポートしてない。
アホなので、これ知らなかった。けっこう衝撃。
以下のSQLクエリはUPDATEやINSERTやDELTEとかのテーブルに変更をかける内容。
ケース1
$dbh->exec("UPDATE MyISAMのテーブル");//M1 $dbh->exec("UPDATE InnoDBのテーブル");//I1 /* トランザクションを開始する。オートコミットがオフになる */ $dbh->beginTransaction(); $dbh->exec("UPDATE MyISAMのテーブル");//M2 $dbh->exec("UPDATE InnoDBのテーブル");//I2 exit; //オートコミットオフのまま処理終了 $dbh->exec("UPDATE MyISAMのテーブル");//M3 $dbh->exec("UPDATE InnoDBのテーブル");//I3
■結果:
- M1,I1 : M1,I1の時点で実行される(トランザクション貼ってないので、オートコミット)
- M2:M2の時点で実行される(MyISAMはtransaction効かない)
- I2:実行されない(オートコミットがオフになっているのでcommitされなかった場合、処理終了時点で自動ロールバックがかかる)
- M3,I3:もちろん実行されない
MyISAMはトランザクションサポートしてないので,beginTransactionもcommitもrollbackもへったくれもなく、読み込んだところで実行される。
ケース2
/* トランザクションを開始する。オートコミットがオフになる */ $dbh->beginTransaction(); $dbh->exec("UPDATE MyISAMのテーブル");//M1 $dbh->exec("UPDATE InnoDBのテーブル");//I1 $dbh->exec("UPDATE InnoDBのテーブル");//I2 $dbh->commit();//C //コミットしたのでトランザクション終了し、オートコミットオンに戻る $dbh->exec("UPDATE MyISAMのテーブル");//M2 $dbh->exec("UPDATE InnoDBのテーブル");//I2 $dbh->exec("UPDATE InnoDBのテーブル");//I3 //ここでcommit();とか書くとthere is no transactionなんちゃらのエラー出る。
■結果:
- M1:M1の時点で実行される
- I1,I2:Cの時点で実行される
- M2:M2の時点で実行される
- I2:I2の時点で実行される
- I3:I3の時点で実行される
結論:MyISAMは特段の理由がない限り採用するな
基本的にエンジンはInnoDBで、SELECT文しか使わないテーブルに対してのみ例外的にMyISAMを使用するってことで憶えておくわ。
あと強制終了させたい場合を除いて関数の中ではexit;を使わんほうがいいみたいね。
職場の人のコードみるとexit多用されてたからずっとマネしてたら、
別の人から汎用的なメソッドの中でのexitは不適切と教えて貰った。
呼び出し元の処理も終わっちゃうので、再利用しづらくなる。
こういう経験に基づくアドバイスは本当にありがたい。
めんどくさい分岐させずに、関数内の以後の処理を走らせたくないときは、
シンプルにreturn null;でいいのかね。