Ubah tabel pada database produksi langsung

24

Bagaimana kebanyakan sistem basis data "populer" (MySQL, Postgres ...) menangani perubahan tabel pada basis data produksi langsung (seperti menambah, menghapus, atau mengubah jenis kolum)?

Saya tahu cara yang benar adalah untuk membuat cadangan semua jadwal downtime dan kemudian lakukan perubahan.

Tetapi ... apakah ada sistem basis data saat ini yang mendukung melakukan hal-hal ini "online" tanpa menghentikan apa pun? (mungkin hanya menunda kueri yang mereferensikan kolom yang baru saja diubah / dihapus)

Dan apa yang terjadi ketika saya hanya melakukan ALTER TABLE...pada live database yang sedang berjalan? Apakah semuanya berhenti ketika ini terjadi? Bisakah data rusak? dll.

Sekali lagi, saya kebanyakan mengacu pada Postgres atau MySQL karena ini yang saya temui.

(Dan, ya, kapan saja saya harus melakukan ini sebelum saya melakukannya "dengan cara yang benar", membackup semuanya, menjadwalkan downtine dll ... tapi saya hanya ingin tahu apakah mungkin untuk melakukan hal-hal semacam ini dan hal-hal "cepat dan kotor "atau jika ada sistem DB yang benar-benar memiliki dukungan untuk perubahan skema" cepat, hidup dan kotor ")


Seseorang baru saja menyarankan Perubahan Skema Online untuk MySQL dari skrip Facebook (dengan tutorial di sini dan sumber di sini ) ... sepertinya cara yang bagus untuk mengotomatiskan serangkaian cara "hacky" untuk melakukannya ... adakah yang pernah menggunakannya dalam sesuatu yang menyerupai produksi?

NeuronQ
sumber
3
Catatan: "cara yang benar" khusus adalah relatif untuk MySQL dan bukan untuk PostgreSQL. "Cara yang benar" di PostgreSQL biasanya sangat mudah, meskipun dapat terlibat. Penggunaan pg_reorgdapat membantu dengan skenario yang lebih sulit.
Sean
Saya ingin sekali memiliki video terperinci tentang ini, dengan seseorang menjelaskan sebanyak mungkin strategi.
Sandeepan Nath

Jawaban:

22

Ketika Anda mengeluarkan sebuah ALTER TABLEdi PostgreSQL, ia akan mengambil ACCESS EXCLUSIVEkunci yang memblokir semuanya termasukSELECT . Namun, kunci ini bisa sangat singkat jika tabel tidak memerlukan penulisan ulang, tidak ada yang baru UNIQUE, CHECKatau FOREIGN KEYkendala membutuhkan pemindaian tabel penuh yang mahal untuk memverifikasi, dll.

Jika ragu, umumnya Anda bisa mencobanya! Semua DDL di PostgreSQL bersifat transaksional, jadi cukup baik untuk membatalkan ALTER TABLEjika terlalu lama dan mulai menyimpan pertanyaan lain. Level kunci yang dibutuhkan oleh berbagai perintah didokumentasikan di halaman penguncian .

Beberapa operasi yang biasanya lambat dapat dipercepat agar aman untuk dilakukan tanpa downtime. Misalnya, jika Anda memiliki meja tdan Anda ingin mengubah kolom customercode integer NOT NULLuntuk textkarena pelanggan telah memutuskan semua pelanggan kode sekarang harus dimulai dengan X, Anda bisa menulis:

ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );

... tapi itu akan mengunci seluruh tabel untuk penulisan ulang. Begitu juga menambahkan kolom dengan a DEFAULT. Ini dapat dilakukan dalam beberapa langkah untuk menghindari kunci panjang, tetapi aplikasi harus mampu mengatasi duplikasi sementara:

ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;

Hal ini hanya akan mencegah menulis untuk tselama proses tersebut; nama kunci EXCLUSIVEagak menipu karena mengecualikan semuanya kecualiSELECT ; yang ACCESS EXCLUSIVEmodus adalah satu-satunya yang tidak termasuk benar-benar everyting. Lihat mode kunci . Ada risiko bahwa operasi ini dapat mengalami kebuntuan-kembalikan karena peningkatan kunci yang diperlukan oleh ALTER TABLE, tetapi paling buruk Anda hanya harus melakukannya lagi.

Anda bahkan dapat menghindari kunci itu dan melakukan semuanya secara langsung dengan membuat fungsi pemicu pada tsetiap kali ada INSERTatau UPDATEmasuk, secara otomatis customercode_newberasal dari customercode.

Ada juga alat bawaan seperti CREATE INDEX CONCURRENTLYdan ALTER TABLE ... ADD table_constraint_using_indexyang dirancang untuk memungkinkan DBA mengurangi durasi penguncian eksklusif dengan melakukan pekerjaan lebih lambat dengan cara yang ramah konkurensi.

The pg_reorgalat atau penggantinya pg_repackdapat digunakan untuk beberapa meja operasi restrukturisasi juga.

Craig Ringer
sumber
1
Hal penting dalam apa yang dikatakan @Craig adalah, "jika itu tidak perlu ditulis ulang." Menggunakan an ALTER TABLE t ADD COLUMN i INTadalah operasi cepat (biasanya <1ms) setelah kunci diperoleh. Namun, mendapatkan kunci dapat membuat antrian koneksi, jadi itu bukan "gratis" ... meskipun itu dunia lebih baik daripada apa yang harus Anda lakukan di MySQL. Menambahkan NOT NULLkendala lebih sulit dan tidak untuk berpura-pura hati.
Sean
Tampaknya menjadi konsensus yang pg_repackmerupakan penerus yang lebih baik dari pg_reorg.
Erwin Brandstetter
Jawaban yang bagus, mengenai menambahkan kolom dengan default (atau dihitung) cara yang kurang "memblokir" adalah membuat seluruh tabel baru, memblokir tabel lama untuk menyisipkan / memperbarui / menghapus tetapi memungkinkan memilih dan mengisi yang baru. Akhirnya mengeluarkan kunci eksklusif singkat di meja lama untuk pilih, hapus dan ganti nama baru menjadi lama. Bergantung pada skenario Anda, Anda bahkan dapat mulai mengisi yang baru tanpa memblokir sisipan pada yang lama dan mengeluarkan kunci eksklusif tepat saat memecahkan diff (semoga hanya menyisipkan beberapa catatan baru)
jean
7

Percona telah hadir dengan alatnya sendiri untuk melakukan perubahan skema online

Alat ini disebut pt-online-schema-change

Ini melibatkan pemicu, jadi silakan baca dokumentasi dengan cermat.

Menurut Dokumentasi, operasi utama yang dilakukan adalah

  • Cek kewarasan
  • Chunking
  • Perubahan skema online
    • Buat dan ubah tabel sementara
    • Tangkap perubahan dari tabel ke tabel sementara
    • Salin baris dari tabel ke tabel sementara
    • Sinkronkan tabel dan tabel sementara
    • Tukar / ganti nama tabel dan tabel sementara
    • Membersihkan
RolandoMySQLDBA
sumber
terima kasih, sepertinya versi "teruji" dari pendekatan Facebook yang dapat saya percayai lebih banyak ...
NeuronQ
pt-online-schema-change jelas merupakan cara yang lebih disukai untuk melakukan ini jika Anda menjalankan server MySQL Anda sendiri. Pada Percona Tools 2.2, (sayangnya) mereka tidak mendukung RDS / Aurora di AWS. pt-online-schema-change memasukkan pemicu pada tabel sumber untuk menyalin baris (prioritas rendah untuk MyISAM) ke table_temp tujuan dan melakukan drop penguncian cepat tunggal dan ganti nama di akhir ketika semua baris disinkronkan antara sumber dan tujuan meja.
phpguru
6

Mematikan sistem dan melakukan semua perubahan sekaligus mungkin sangat berisiko. Jika terjadi kesalahan, dan sering kali terjadi, tidak ada jalan kembali yang mudah.

Sebagai pengembang Agile, kadang-kadang saya perlu memperbaiki tabel tanpa downtime sama sekali, karena tabel tersebut sedang dimodifikasi dan dibaca.

Pendekatan berikut memiliki risiko rendah, karena perubahan dilakukan dalam beberapa langkah berisiko rendah yang sangat mudah untuk dibatalkan:

  • Pastikan semua modul yang mengakses tabel dilindungi dengan baik dengan tes otomatis.
  • Buat tabel baru. Ubah semua prosedur yang memodifikasi tabel lama, sehingga mereka memodifikasi tabel lama dan baru.
  • Migrasikan data yang ada ke struktur baru. Lakukan dalam batch bertubuh kecil, sehingga tidak berdampak serius terhadap kinerja keseluruhan pada server.
  • Pastikan migrasi data berhasil.
  • Arahkan kembali beberapa prosedur pemilihan dari tabel lama ke yang baru. Gunakan tes otomatis untuk memastikan bahwa modul yang diubah masih benar. Pastikan kinerja mereka dapat diterima. Menyebarkan prosedur yang diubah.
  • Ulangi langkah sebelumnya hingga semua laporan menggunakan tabel baru.
  • Ubah prosedur yang memodifikasi tabel, sehingga mereka hanya mengakses tabel baru.
  • Arsipkan tabel lama dan hapus dari sistem.

Kami telah menggunakan pendekatan ini berkali-kali untuk mengubah tabel produksi langsung besar tanpa downtime, tanpa masalah sama sekali.

AK
sumber
3
Hebat ... tapi itulah jenis "rasa sakit" yang ingin saya hindari :)
NeuronQ
@NeuronQ " Tidak ada jalan kembali yang mudah " - ada di Postgres: cukup masukkan semuanya ke dalam transaksi dan rollbackjika terjadi kesalahan.
a_horse_with_no_name
2

Ya, banyak database modern akan memungkinkan Anda untuk hanya menambahkan kolom atau mengubah karakteristik kolom, seperti menambah atau menghapus nullable.

Jika Anda menjatuhkan kolom, data akan hilang, tetapi tidak ada banyak ketakutan akan korupsi.

Marlin Pierce
sumber
0

Alat Percona menggunakan pemicu untuk membantu mengubah, dan itu tidak berfungsi dengan baik jika meja Anda sudah memiliki pemicu yang ada. Saya akhirnya harus menulis yang benar-benar menangani pemicu yang ada dengan baik, karena mereka sangat penting untuk basis data kami https://github.com/StirlingMarketingGroup/smg-live-alter

Brian berkata Reinstate Monica
sumber
-1

Untuk menjawab pertanyaan tentang apa yang terjadi dengan ALTER TABLEpernyataan, itu tergantung pada sejauh mana perubahan Anda. Dalam kasus tertentu, jika Anda menambahkan kolom baru, setidaknya di MS SQL Server, mesin akan membuat salinan sementara dari tabel, sementara itu menciptakan definisi tabel baru, dan kemudian menyisipkan data kembali ke sana. Selama durasi perubahan, tabel tersebut karenanya tidak dapat diakses oleh pengguna.

Contoh operasi spesifik untuk server MSSQL ada di sini: http://support.microsoft.com/kb/956176/en-us

Saya akan berasumsi bahwa RMDB lain memiliki metode yang serupa, meskipun implementasi yang tepat akan menjadi sesuatu yang harus Anda verifikasi dengan dokumentasi vendor.

SchmitzIT
sumber
-1 Ini sepenuhnya salah untuk SQL Server: "Jika Anda menambahkan kolom baru, setidaknya di MS SQL Server, mesin akan membuat salinan sementara dari tabel, sementara itu menciptakan definisi tabel baru, dan kemudian menyisipkan data kembali di sana "
AK
@AlexKuznetsov - Saya menemukan garis sebelumnya, serta tautan dengan beberapa kasus yang tercantum akan menjelaskan ini tidak selalu terjadi. Saya mengubah kalimat agar lebih mencerminkan hal ini.
SchmitzIT
1
Anda menyebutkan perilaku GUI, SSMS, bukan perilaku SQL Server itu sendiri. Mengikuti tautan Anda, sarannya adalah menggunakan T-SQL secara langsung untuk membuat perubahan DDL. SSMS bukan alat yang sangat baik untuk mengubah DDL.
AK
@AlexKuznetsov - Saya membaca artikel yang mengatakan bahwa ada risiko yang terlibat, tetapi tidak sebagai penghalang. Lagi pula, saya tidak menautkan artikel untuk bit GUI, tetapi sebagai indikasi dari beberapa operasi yang mengarah pada pernyataan ALTER yang mengarah ke pembuatan tabel sementara karena perubahan dalam struktur data yang mendasarinya. Saya belum menguji apakah hal yang sama persis berlaku ketika mengeluarkan pernyataan langsung dari T-SQL, tapi saya akan berpikir prosesnya sangat mirip dan bahwa SL Server melakukan kerja keras di belakang layar.
SchmitzIT
Anda dapat memulai Profiler, menjalankan pernyataan ALTER TABLE secara langsung, dan melihat apa yang terjadi. Kemudian Anda dapat mengubah tabel melalui kotak dialog, dan lihat sendiri perintah yang dijalankan.
AK