mysqliでトランザクション – 1件でも失敗したらロールバック

2019-08-03PHPSQL

あるテーブルの項目「納期日」を更新したら、他のテーブルに存在している「納期日」も同じ日時で更新したい。
これらのテーブルはこの「納期日」でつながっているので、整合性を保つため 1 件でも失敗したら全て更新前の値に戻したい。
こういうときは、トランザクションを使う。 mysqli でのトランザクションの実装方法をメモ。

まず大前提として、使っている DB がトランザクションが使える InnoDB でないといけない。
MyISAM はトランザクションをサポートしてないので、トランザクションという処理を扱うことはできない。
mysqli でトランザクションの実装
try{
	// トランザクション開始
	$mysqli->begin_transaction();
	try {
		// table A の UPDATE
		$sql1 = "UPDATE table A, table B SET A.deliverydate=? WHERE A.name=? A AND A.deliverydate = B.deliverydate";
		$stm1=$mysqli->prepare($sql1);
		$stm1->bind_param("ss", $delivery, $name);
		$stm1->execute();
		// table C の UPDATE
		$sql2 = "UPDATE table C, table B SET C.deliverydate=? WHERE C.productno=? AND C.deliverydate = B.deliverydate";
		$stm2=$mysqli->prepare($sql2);
		$stm2->bind_param("si", $delivery, $productno);
		$stm2->execute();
		// table B の UPDATE
		$stm3=$mysqli->prepare("UPDATE table B set deliverydate=? WHERE id=?");
		$stm3->bind_param("si", $delivery, $id);
		$stm3->execute();
		// コミット
		$mysqli->commit();
		echo 'コミットしました。';
	} catch( Exception $e ){
		// エラーが発生したらロールバック
		$mysqli->rollback();
		throw $e;
		// echo 'Error:'.$e->getMessage();
		// exit;
	}
} catch (Exception $e) {
    throw $e;
}

トランザクションの開始には、 $mysqli->autocommit(FALSE); を使って、オートコミットを無効にする方法もあるようだが、これを記述すると、これ以降の処理でもオートコミットが無効になる。

Posted by Agopeanuts