質問: ' . json_encode($result, JSON_UNESCAPED_UNICODE) );`を書いており、これは出力されました。よって`// エラーなら ROLLBACK する`というのは分岐できているようです。 なのにこの一行前の`$wpdb->query('ROLLBACK'); // ここで ROLLBACK が効かず、wp_mains にだけ値が入ってしまうのが問題です`のROLLBACKが効かないということです。 続いてこちらの記事()を見つけ、ストレージエンジンがInnoDBでないとROLLBACKが効かないのだという情報を得まして確認したのですが、すべてのテーブルはInnoDBで間違いございませんでした。 ### バージョン情報等 WordPressは5.4です。 MySQLは`select version();`で`10.0.33-MariaDB`でした。 上記ソースコードで間違っている点、あやしい点、なおすべき点などお心あたりのある方がいらっしゃいましたらご回答いただけましたら幸いでございます。 初心者のコードにつき冗長であったり見にくかったり等あるかと思いますが、どうぞよろしくお願い致します。
回答: ### 問題の原因 原因は以下のコード ``` // トランザクションとロックするテーブル $wpdb->query("START TRANSACTION"); $wpdb->query("LOCK TABLES wp_mains WRITE, wp_sub1s WRITE"); ``` ### 解決方法 `LOCK TABLES`する場合、ドキュメント()の最後の「正しい方法」に則って以下のようにしなければならない。 ``` // 「正しい方法」に則って以下のようにしなければならない $wpdb->query('SET autocommit=0'); // これで0を指定 // $wpdb->query('START TRANSACTION'); // これは不要 $wpdb->query('LOCK TABLES wp_mains WRITE, wp_sub1s WRITE'); ``` なぜならデフォルトでは`autocommit=1`となっており、するとSQLは実行されるたびにコミットされ、`ROLLBACK`が効かなくなるため。 尚、なぜ`START TRANSACTION`が不要かというと、このページ()によれば、0にした場合 >この場合のトランザクションは、SQL文の実行によって暗黙的に開始する とのこと。 ### 補足 ちなみに、`LOCK TABLES`しない場合ならば、以下のように`START TRANSACTION`だけでOK。 ``` // START TRANSACTION だけでOK $wpdb->query("START TRANSACTION"); ``` なぜなら、同ページ()によれば次の通りで、 >オートコミットを有効にした場合(デフォルトで有効) >1.START TRANSACTION文を実行した場合 >単一のSQL文が実行されただけではコミットせず、COMMIT文を実行した時点で初めてコミットされる。ROLLBACK文を実行すればロールバックする。 つまり`autocommit=1`であっても`START TRANSACTION`だけ実行してやればCOMMIT文の実行までコミットされず`ROLLBACK`が効くため。 ### 残った疑問1 **補足**にある「>`START TRANSACTION`だけ実行してやればCOMMIT文の実行までコミットされず」が正しいならば、**問題の原因**にあるコードでもコミットされないはずで、問題は発生しないはずで、**解決方法**のように`autocommit=0`を指定する必要はないはず。 それがなぜ`LOCK TABLES`する場合には`autocommit=0`を指定しなければならなくなるのかが疑問。 ### 残った疑問2 さらに解決方法でautocommit=0とした直後に、autocommitを確認するとなぜか1になってるという点も疑問... ``` // 解決方法 $wpdb->query('SET autocommit=0'); $wpdb->query("LOCK TABLES wp_mains WRITE, wp_sub1s WRITE"); // autocommit を確認 $result['check_autocommit'] = $wpdb->query("SELECT @@autocommit"); // なぜか1になってる ```