主要なSQLデータベースでCREATE TABLEおよびALTER TABLEステートメントをロールバックすることは可能ですか?


108

DDLを発行するプログラムに取り組んでいます。CREATE TABLE同様のDDLをロールバックできるかどうかを知りたい

  • Postgres
  • MySQL
  • SQLite

各データベースがDDLを使用してトランザクションを処理する方法を説明します。


このスレッドを補完するだけでは、H2はまたによると、SQLコマンドのほとんどのトランザクションDDL文をサポートしていませんこの
Gabriel Paim

回答:


148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysisは、PostgreSQLの観点からこの問題の概要を提供します。

このドキュメントによると、DDLはトランザクション対応ですか?

  • PostgreSQL-はい
  • MySQL-いいえ。DDLは暗黙的なコミットを引き起こします
  • Oracle Database 11gリリース2以上-デフォルトではありませんが、エディションベースの再定義と呼ばれる代替手段が存在します
  • 古いバージョンのOracle-いいえ。DDLは暗黙的なコミットを引き起こします
  • SQL Server-はい
  • Sybase Adaptive Server-はい
  • DB2-はい
  • Informix-はい
  • Firebird(Interbase)-はい

SQLiteにもトランザクションDDLがあるようです。SQLiteでステートメントを作成することができましROLLBACKCREATE TABLE。そのCREATE TABLEドキュメントでは、特別なトランザクションの「落とし穴」については触れられていません。


8
ただし、sqliteのデフォルトのPythonドライバーは、トランザクションSQLを防ぎます。bugs.python.org/issue10740
joeforker

したがって、答えは「はい、MySQLまたは古いバージョンのOracleを使用していない限り、ロールバックできます。」
rjmunro

いいえ、リストされているもの以外にも他のSQLデータベースがあります。
joeforker

3
MariaDBには、トランザクションDDLサポートを追加するための未解決の問題があります:jira.mariadb.org/browse/MDEV-4259。投票してください。
ギリ

1
やや限定的なALTER TABLESQLiteのステートメントもロールバックできます。ドキュメントでは明示的に言及されていません。言及されているのは、トランザクション内で「高度な」変更を実行する方法です。
トーマス

32

PostgreSQLは、ほとんどのデータベースオブジェクト(確かにテーブル、インデックスなど)にトランザクションDDLを持っていますが、データベース、ユーザーにはありません。ただし、実際にはすべてのDDLがACCESS EXCLUSIVEターゲットオブジェクトをロックし、DDLトランザクションが完了するまで完全にアクセスできなくなります。また、すべての状況が完全に処理されるわけではありません。たとえば、foo別のトランザクションがそれをドロップして置換テーブルを作成しているときにテーブルから選択しようとするとfoo、ブロックされたトランザクションは、新しいfooテーブルを見つけるのではなく、最終的にエラーを受け取ります。(編集:これはPostgreSQL 9.3以前で修正されました)

CREATE INDEX ... CONCURRENTLY 例外です。3つのトランザクションを使用してインデックスをテーブルに追加し、同時に更新を許可するため、トランザクション内でそれ自体を実行することはできません。

また、データベース保守コマンドVACUUMはトランザクションでは使用できません。


foo別のトランザクションがドロップして再作成しているときにテーブルから選択しようとすると、古いバージョンまたはエラーでOK だと私は主張します。新しいバージョンはまだコミットされていないので、私は問題があります。同時トランザクションアクセスではトランザクションを再開するための準備をする必要があるため、エラーで大丈夫です。エラーが必要以上に頻繁に発生すると、パフォーマンスが低下する可能性がありますが、それでも問題はありません。
Jan Hudec

1
@JanHudec:新しいテーブルのコミットされていないバージョンは表示されず、削除または再作成したトランザクション全体の結果のみが表示されます。つまり、テーブルを削除、再作成、および再投入するトランザクションは、他のプロセスがそのテーブルから選択することに対して事実上アトミックです。(ただし、テーブルのスキーマを読み取ろうとするとすぐにすべてがブロックされます)
araqnid

5

厳密に言えば「ロールバック」ではありませんが、OracleでFLASHBACKコマンドを使用して、これらのタイプの変更を取り消すことができます(データベースがそれをサポートするように構成されている場合)。


5

他の回答はかなり古くなっているようです。

2019年現在:

  • Postgresは、多くのリリースでトランザクションDDLをサポートしています。
  • SQLiteは、多くのリリースでトランザクションDDLをサポートしています。
  • MySQLは8.0(2018年にリリースされた)以降、Atomic DDLをサポートしています。

1
MySQL 8のアトミックDDLは、アトミックDDLステートメントのみを参照し、トランザクションステートメントを参照しないことに注意してください。DDLステートメントは、アトミックかどうかに関係なく、ほとんどの場合暗黙のコミットを引き起こすため、別のトランザクション内で実行できません(たとえばSTART TRANSACTION ... COMMIT;、同じトランザクションの後者のDDLステートメントが失敗した場合でも、トランザクション内のDDLステートメントをロールバックすることはできません。devのメモを参照してください 。 mysql.com/doc/refman/8.0/en/...
Lacek

4

MySQLではできません。非常に馬鹿げているように見えますが、本当です...(承認された回答に従って)

「InnoDBのCREATE TABLEステートメントは単一のトランザクションとして処理されます。これは、ユーザーからのROLLBACKが、そのトランザクション中にユーザーが作成したCREATE TABLEステートメントを取り消さないことを意味します。」

https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html

いくつかの方法を試しましたが、ロールバックされません。

回避策は、単に失敗フラグを設定し、クエリの1つが失敗した場合に「テーブルのtblnameを削除する」ことです。


1
くそー。特定の(作成)テーブルが過去1時間失敗しても、以前に作成されたテーブルが消えない理由を理解しようとしています。MariaDB(XAMPPがMySQLからMariaDBに切り替えられました)を使用していますが、ケースは同じです。これはばかげています:|
アキヌリ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.