MySQLのSAVEPOINTの仕様を調べる

MySQLのトランザクションのネスト(SAVEPOINT)について気になったので調べてみました
使用したMySQLのバージョンは8.0.24です
公式ドキュメントは コチラ

START TRANSACTIONを実行せずにSAVEPOINTを実行できるのか?

結論: いきなりSAVEPOINTを実行できます
以下の例は、START TRANSACTIONを実行せずにSAVEPOINTを実行しているが正常に完了しレコードが挿入されます。

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
COMMIT;

ロールバックも出来ます。
以下の例は、レコードが挿入されません。

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
ROLLBACK;

無名のSAVEPOINTは作れるのか?

SAVEPOINT identifier

結論: 無名のSAVEPOINTは作成できません。
シンタックスエラーになります

複数のSAVEPOINTをまとめてロールバックできるか?

結論: できる
以下のサンプルは1件もINSERTされない

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
SAVEPOINT test2;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
SAVEPOINT test3;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
ROLLBACK;

部分的にロールバックした後、コミットした場合の挙動は?

以下のサンプルでは、最初にINSERTした1件だけがコミットされる

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
SAVEPOINT test2;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
ROLLBACK TO SAVEPOINT test2;
COMMIT;

部分的にリリースした後、コミットした場合の挙動は?

以下のサンプルでは2件ともコミットされる
(リリースはSAVEPOINTを削除するが、変更そのものは残る)

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
SAVEPOINT test2;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
RELEASE SAVEPOINT test2;
COMMIT;

部分的にリリースした後、ロールバックした場合の挙動は?

以下のサンプルでは2件ともロールバックされる

SAVEPOINT test1;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
SAVEPOINT test2;
INSERT INTO users(name, age, created_at) VALUES("test", 20, "2010-12-31 23:59:59");
RELEASE SAVEPOINT test2;
ROLLBACK;

コメントする