# トランザクションについて # 伝えたいこと - ACIDの原子性とは、トランザクション内でのQueryを適用か不適用か - エラー発生時にトランザクションのCommit/RollBackをどう取り扱うかは、アプリケーションの責務である # 発端 [プログラミングスクール](https://www.value-press.com/pressrelease/247307)でメンターやってます。 「SQLゼロからはじめるデータベース操作」を読んだ、生徒さんからの質問がありました。 > PostgreSQLではトランザクションの中のSQL文が一つでもエラーになると、後続のSQL文も全てエラーになり強制的にロールバックする。 > PostgreSQL以外はエラーとなるSQL文だけが実行されず、それ以外のSQL文は実行されてコミットされる。例えばトランザクションの中で、3つのSQL文の内1つがエラーになっても2つは実行されてコミットされる。 上記からPostgreSQLを除くRDBMSは、原子性を守ることができないはないか? # トランザクション内でエラーが発生した際の挙動がPostgreSQL、MySQLで異なる 初動では、書籍の出版が古くACID特性がないMyISAMを紹介していると推測し、InnoDBの動作確認したところ思わぬ挙動を発見しました。 ```sql Insert into users (email) values ("imaharu@example.com"); START TRANSACTION; Insert into users (email) values ("imaharu@example.com"); Insert into users (email) values ("hoge@example.com"); commit; select count(*) from users; # 2 ``` 試しに、PostgreSQLの挙動を確認すると失敗した場合に後述のクエリ実行のエラーになり、RollBackすることがわかりました。 ```sql BEGIN; Insert into users (email) values ('imaharu@example.com'); ERROR: duplicate key value violates unique constraint "users_email_key" DETAIL: Key (email)=(imaharu@example.com) already exists. Insert into users (email) values ('hoge@example.com'); ERROR: current transaction is aborted, commands ignored until end of transaction block COMMIT; ROLLBACK select count(*) from users; # 1 ``` # 実験(LTのみ) やる # 原子性に関する認識 ## 過去 トランザクション内で全てはクエリは、成功か失敗 トランザクション内でエラーが発生した場合、発行したクエリをRollBack。 ## 現在 トランザクション内のクエリを適用か不適用 # 回答結論 トランザクション内で発生した際の挙動は、アプリケーションの責務である。 DataBaseはトランザクションを制御するためのインターフェースを提供する。 # 調査してないこと - 非対話実行では、挙動が異なる - [RollBackは、PostgreSQL特有の挙動説](https://www.postgresql.jp/sites/default/files/2017-05/Introdution_to_Transaction_20170527d.pdf) ## 次回のLTで発表したいこと - MySQLのグローバル変数とセッション変数 - ActiveRecord::Transactionsの実装を紹介 - ロック - 占有ロック、共有ロック - ロックとは、トランザクション分離レベルを制御する機能 - トランザクション分離レベル # サンプルコード https://github.com/imaharu/mysql_test ## 議論メモ - https://twitter.com/imaharuTech/status/1278834000367247360?s=20 - https://twitter.com/zipperpull/status/1278845103180615680?s=20 - https://www.value-press.com/pressrelease/247307 ## 参考 https://dev.mysql.com/doc/refman/5.6/ja/myisam-storage-engine.html https://dev.mysql.com/doc/refman/5.6/ja/innodb-default-se.html https://dev.mysql.com/doc/refman/5.6/ja/glossary.html#glos_transaction https://www.postgresql.jp/document/12/html/tutorial-transactions.html https://qiita.com/song_ss/items/38e514b05e9dabae3bdb https://open-groove.net/mysql/autocommit https://atsuizo.hatenadiary.jp/entry/2019/02/26/142814