###前提・実現したいこと
親関数の中で実行される子関数でエラーがおきたとき、親関数のLOCK TABLES
をROLLBACK
させたいです。
###発生している問題
親関数のLOCK TABLES
をROLLBACK
させることができません。
###該当のソースコード
親関数my_insert_wp_fruits
の中で、子関数my_insert_wp_vegetables
が実行されます。
(それぞれ独自に実行するケースがあるため独立させています。)
さて以下5行目の$val
は、子関数の最後に更新されるwp_vegetables2
テーブルを更新する値ですが、ここをCREATE
で設定したVARCHAR(3)
以上の文字にしてエラーを起こしてみました。
しかしROLLBACK
が効くのは子関数でLOCK TABLES
をかけたwp_vegetables1
とwp_vegetables2
だけで、wp_fruits1
とwp_fruits2
はINSERTが成功してしまうのです。
これを親関数のLOCK TABLES
にまでさかのぼって、wp_fruits1
とwp_fruits2
も含めてROLLBACK
させられませんでしょうか?
php
1// 4つのテーブル作成 2create_tables(); 3 4// 実行 5$val = 'val'; // ここを VARCHAR(3) 以上の文字にしてエラーを起こしても、wp_fruits1 と wp_fruits2 は ROLLBACK が効かない 6$fruits_datas = [ 'fruits1'=>['col'=>'val'], 'fruits2'=>['col'=>'val'] ]; 7$vegetable_datas = [ 'vegetables1'=>['col'=>'val'], 'vegetables2'=>['col'=>$val] ]; 8$result = my_insert_wp_fruits($fruits_datas,$vegetable_datas); 9var_dump( $result ); 10 11// 親関数 ( wp_fruits1 と wp_fruits2 を INSERT ) 12function my_insert_wp_fruits($fruits_datas,$vegetable_datas=[]){ 13 global $wpdb; 14 $wpdb->query('SET autocommit=0'); 15 $sql = "LOCK TABLES wp_fruits1 WRITE, wp_fruits2 WRITE"; 16 $wpdb->query($sql); 17 18 $result = null; 19 try { 20 21 // wp_fruits1 を保存 22 $fruits1 = $wpdb->insert( 'wp_fruits1', $fruits_datas['fruits1'], ['%s'] ); 23 if( ! $fruits1 ){ 24 throw new Exception("fruits1 の INSERT でエラー"); 25 }else{ 26 $fruits1_id = $wpdb->insert_id; 27 28 // wp_fruits2 を保存 29 $fruits2 = $wpdb->insert( 'wp_fruits2', $fruits_datas['fruits2'], ['%s'] ); 30 if( ! $fruits2 ){ 31 throw new Exception("fruits2 の INSERT でエラー"); 32 }else{ 33 $fruits2_id = $wpdb->insert_id; 34 35 // 以下の子関数でエラーが出たとき、親関数を ROLLBACK させたい 36 $vegetable_ids = my_insert_wp_vegetables($vegetable_datas); 37 if( isset($vegetable_ids['error']) ){ 38 throw new Exception("my_insert_wp_vegetables でエラー"); 39 } 40 } 41 } 42 43 // 問題なければ 44 $result = ['fruits1_id'=>$fruits1_id,'fruits2_id'=>$fruits2_id]; 45 $result = array_merge( $result, $vegetable_ids ); 46 $wpdb->query('COMMIT'); 47 48 } catch (Exception $e) { 49 $wpdb->query('ROLLBACK'); 50 $result['error'] = $e->getMessage(); 51 } finally { 52 $wpdb->query('UNLOCK TABLES'); 53 } 54 55 return $result; 56} 57 58// 子関数 ( wp_vegetables1 と wp_vegetables2 を INSERT ) 59function my_insert_wp_vegetables($vegetable_datas){ 60 global $wpdb; 61 $wpdb->query('SET autocommit=0'); 62 $sql = "LOCK TABLES wp_vegetables1 WRITE, wp_vegetables2 WRITE"; 63 $wpdb->query($sql); 64 65 $result = null; 66 try { 67 68 // wp_vegetables1 を保存 69 $vegetables1 = $wpdb->insert( 'wp_vegetables1', $vegetable_datas['vegetables1'], ['%s'] ); 70 if( ! $vegetables1 ){ 71 throw new Exception("vegetables1 の INSERT でエラー"); 72 }else{ 73 $vegetables1_id = $wpdb->insert_id; 74 75 // wp_vegetables2 を保存 76 $vegetables2 = $wpdb->insert( 'wp_vegetables2', $vegetable_datas['wp_vegetables2'], ['%s'] ); 77 if( ! $vegetables2 ){ 78 throw new Exception("vegetables2 の INSERT でエラー"); 79 }else{ 80 $vegetables2_id = $wpdb->insert_id; 81 } 82 } 83 84 // 問題なければ 85 $result = ['vegetables1_id'=>$vegetables1_id,'vegetables2_id'=>$vegetables2_id]; 86 $wpdb->query('COMMIT'); 87 88 } catch (Exception $e) { 89 $wpdb->query('ROLLBACK'); 90 $result['error'] = $e->getMessage(); 91 } finally { 92 $wpdb->query('UNLOCK TABLES'); 93 } 94 95 return $result; 96} 97 98// 4つのテーブル作成 99function create_tables(){ 100 global $wpdb; 101 $tables = ['fruits1','fruits2','vegetables2','vegetables1']; 102 foreach( $tables as $table ){ 103 $prefixed_table = $wpdb->prefix . $table; 104 $sql = "CREATE TABLE IF NOT EXISTS $prefixed_table ( 105 ID INT(1) UNSIGNED NOT NULL AUTO_INCREMENT, 106 col VARCHAR(3) NOT NULL, 107 PRIMARY KEY (ID) 108 );"; 109 add_option($table."_version", '1.0'); 110 $wpdb->query($sql); 111 } 112} 113
###試したこと
自分なりの解決策としては、親関数の方で、「もし子関数を更新するならLOCK TABLESを追加」というコードを下記のように加える方法ですが…
こういった方法よりも、親関数にさかのぼってROLLBACK
させたいと思っています。
ご指導宜しくお願い申し上げます。
php
1function my_insert_wp_fruits($fruits_datas,$vegetable_datas=[]){ 2 global $wpdb; 3 $wpdb->query('SET autocommit=0'); 4 $sql = "LOCK TABLES wp_fruits1 WRITE, wp_fruits2 WRITE"; 5 6 // もし子関数を更新するならLOCK TABLESを追加 7 if( !empty($vegetable_datas) ){ 8 $sql .= ",wp_vegetables1 WRITE, wp_vegetables2 WRITE" 9 } 10 11 $wpdb->query($sql); 12 13 // 以下同じ 14}
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/29 04:05
2020/06/29 04:11 編集
2020/06/29 04:35