回答:
http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysisは、PostgreSQLの観点からこの問題の概要を提供します。
このドキュメントによると、DDLはトランザクション対応ですか?
SQLiteにもトランザクションDDLがあるようです。SQLiteでステートメントを作成することができましROLLBACK
たCREATE TABLE
。そのCREATE TABLE
ドキュメントでは、特別なトランザクションの「落とし穴」については触れられていません。
PostgreSQLは、ほとんどのデータベースオブジェクト(確かにテーブル、インデックスなど)にトランザクションDDLを持っていますが、データベース、ユーザーにはありません。ただし、実際にはすべてのDDLがACCESS EXCLUSIVE
ターゲットオブジェクトをロックし、DDLトランザクションが完了するまで完全にアクセスできなくなります。また、すべての状況が完全に処理されるわけではありません。たとえば、foo
別のトランザクションがそれをドロップして置換テーブルを作成しているときにテーブルから選択しようとするとfoo
、ブロックされたトランザクションは、新しいfoo
テーブルを見つけるのではなく、最終的にエラーを受け取ります。(編集:これはPostgreSQL 9.3以前で修正されました)
CREATE INDEX ... CONCURRENTLY
例外です。3つのトランザクションを使用してインデックスをテーブルに追加し、同時に更新を許可するため、トランザクション内でそれ自体を実行することはできません。
また、データベース保守コマンドVACUUM
はトランザクションでは使用できません。
foo
別のトランザクションがドロップして再作成しているときにテーブルから選択しようとすると、古いバージョンまたはエラーでOK だと私は主張します。新しいバージョンはまだコミットされていないので、私は問題があります。同時トランザクションアクセスではトランザクションを再開するための準備をする必要があるため、エラーで大丈夫です。エラーが必要以上に頻繁に発生すると、パフォーマンスが低下する可能性がありますが、それでも問題はありません。
他の回答はかなり古くなっているようです。
2019年現在:
START TRANSACTION ... COMMIT;
、同じトランザクションの後者のDDLステートメントが失敗した場合でも、トランザクション内のDDLステートメントをロールバックすることはできません。devのメモを参照してください 。 mysql.com/doc/refman/8.0/en/...)
MySQLではできません。非常に馬鹿げているように見えますが、本当です...(承認された回答に従って)
「InnoDBのCREATE TABLEステートメントは単一のトランザクションとして処理されます。これは、ユーザーからのROLLBACKが、そのトランザクション中にユーザーが作成したCREATE TABLEステートメントを取り消さないことを意味します。」
https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html
いくつかの方法を試しましたが、ロールバックされません。
回避策は、単に失敗フラグを設定し、クエリの1つが失敗した場合に「テーブルのtblnameを削除する」ことです。