読者です 読者をやめる 読者になる 読者になる

節子、それInnoDBやない!!MyISAMや!!トランザクション周りではまったたった一つの原因

php MySQL

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;でいいのかね。