Apakah mungkin untuk memutar kembali pernyataan CREATE TABLE dan ALTER TABLE dalam database SQL utama?

108

Saya sedang mengerjakan program yang mengeluarkan DDL. Saya ingin tahu apakah CREATE TABLEDDL serupa dan dapat diputar kembali

  • Postgres
  • MySQL
  • SQLite
  • dkk

Jelaskan bagaimana setiap database menangani transaksi dengan DDL.

joeforker
sumber
Hanya untuk melengkapi utas ini, H2 juga tidak mendukung pernyataan DDL transaksional untuk sebagian besar perintah SQL, menurut ini .
Gabriel Paim

Jawaban:

148

http://wiki.postgresql.org/wiki/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis memberikan gambaran umum tentang masalah ini dari perspektif PostgreSQL.

Apakah DDL transaksional menurut dokumen ini?

  • PostgreSQL - ya
  • MySQL - tidak; DDL menyebabkan komit implisit
  • Oracle Database 11g Release 2 dan yang lebih baru - secara default, tidak, tetapi alternatif yang disebut redefinisi berbasis edisi sudah ada
  • Oracle versi lama - tidak; DDL menyebabkan komit implisit
  • SQL Server - ya
  • Sybase Adaptive Server - ya
  • DB2 - ya
  • Informix - ya
  • Firebird (Interbase) - ya

SQLite juga tampaknya memiliki DDL transaksional juga. Saya bisa ROLLBACKmembuat CREATE TABLEpernyataan di SQLite. Its CREATE TABLEdokumentasi tidak menyebutkan khusus setiap transaksional 'Gotchas'.

joeforker
sumber
8
Namun, driver Python default untuk sqlite mencegah SQL transaksional. bugs.python.org/issue10740
joeforker
Jadi jawabannya adalah "Ya, mereka dapat dibatalkan, kecuali Anda menggunakan MySQL atau Oracle versi yang lebih lama."
rjmunro
Tidak, ada database SQL lain selain yang terdaftar.
joeforker
3
Ada masalah terbuka di MariaDB untuk menambahkan dukungan DDL transaksional: jira.mariadb.org/browse/MDEV-4259 . Tolong pilih itu.
Gili
1
ALTER TABLEPernyataan SQLite yang agak terbatas juga dapat dibatalkan. Itu tidak disebutkan secara eksplisit dalam dokumentasi . Apa yang disebutkan di sana adalah bagaimana melakukan perubahan "lanjutan" di dalam transaksi.
Thomas
32

PostgreSQL memiliki DDL transaksional untuk sebagian besar objek database (tentu saja tabel, indeks, dll, tetapi tidak untuk database, pengguna). Namun secara praktis setiap DDL akan mendapatkan ACCESS EXCLUSIVEkunci pada objek target, membuatnya benar-benar tidak dapat diakses hingga transaksi DDL selesai. Selain itu, tidak semua situasi ditangani dengan baik - misalnya, jika Anda mencoba memilih dari tabel foosementara transaksi lain menghapusnya dan membuat tabel pengganti foo, maka transaksi yang diblokir akhirnya akan menerima kesalahan daripada menemukan footabel baru . (Sunting: ini telah diperbaiki di atau sebelum PostgreSQL 9.3)

CREATE INDEX ... CONCURRENTLY luar biasa, ia menggunakan tiga transaksi untuk menambahkan indeks ke tabel sambil mengizinkan pembaruan bersamaan, jadi itu sendiri tidak dapat dilakukan dalam transaksi.

Juga perintah pemeliharaan database VACUUMtidak dapat digunakan dalam transaksi.

araqnid
sumber
Saya berpendapat bahwa jika saya mencoba untuk memilih dari tabel foosementara transaksi lain turun dan membuatnya kembali, maka saya setuju dengan versi lama atau kesalahan. Saya tidak setuju dengan versi baru, karena itu belum dilakukan, jadi saya tidak boleh melihatnya. Saya baik-baik saja dengan kesalahan, karena dalam akses transaksional bersamaan seseorang harus tetap siap untuk memulai kembali transaksi. Jika kesalahan terjadi lebih sering dari yang diperlukan, hal itu dapat menurunkan kinerja, tetapi itu masih benar.
Jan Hudec
1
@JanHudec: Anda tidak akan melihat versi tabel baru yang tidak terikat, hanya hasil dari seluruh transaksi yang membatalkan / membuatnya kembali. yaitu transaksi yang menjatuhkan, membuat ulang, dan mengisi kembali tabel secara efektif merupakan proses lain yang memilih dari tabel itu. (tetapi semuanya akan diblokir segera setelah mereka mencoba membaca skema tabel)
araqnid
5

Meskipun tidak secara tegas disebut sebagai "rollback", di Oracle, perintah FLASHBACK dapat digunakan untuk membatalkan jenis perubahan ini, jika database telah dikonfigurasi untuk mendukungnya.

Dave Costa
sumber
5

Sepertinya jawaban lainnya sudah cukup usang.

Per 2019:

  • Postgres telah mendukung DDL transaksional untuk banyak rilis.
  • SQLite telah mendukung DDL transaksional untuk banyak rilis.
  • MySQL telah mendukung Atomic DDL sejak 8.0 (yang dirilis pada 2018).
PaulMest
sumber
1
Perlu dicatat bahwa Atomic DDL di MySQL 8 hanya mengacu pada pernyataan atomic DDL, tetapi bukan pernyataan transaksional. Pernyataan DDL, atom atau tidak, sebagian besar masih menyebabkan komit implisit dan karenanya tidak dapat dieksekusi dalam transaksi lain (mis START TRANSACTION ... COMMIT;. Jadi, Anda masih tidak dapat mengembalikan pernyataan DDL dalam transaksi jika yang terakhir dalam transaksi yang sama gagal. (Lihat catatan di bawah dev. mysql.com/doc/refman/8.0/en/… )
Lacek
4

Sepertinya tidak dapat dilakukan dengan MySQL , sangat bodoh, tapi benar ... (sesuai jawaban yang diterima)

"Pernyataan CREATE TABLE di InnoDB diproses sebagai transaksi tunggal. Ini berarti ROLLBACK dari pengguna tidak membatalkan pernyataan CREATE TABLE yang dibuat pengguna selama transaksi itu."

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

Mencoba beberapa cara berbeda dan tidak akan mundur ..

Mengatasinya adalah dengan hanya menetapkan tanda kegagalan dan melakukan "drop table tblname" jika salah satu query gagal ..

Robert Sinclair
sumber
1
Sial. Saya telah mencoba untuk mencari tahu mengapa tabel yang dibuat sebelumnya tidak akan hilang ketika tabel (buat) tertentu gagal selama satu jam terakhir. Saya menggunakan MariaDB (XAMPP beralih dari MySQL ke MariaDB), tetapi kasusnya sama. Ini konyol: |
akinuri