Masalah dan Skop
Perkhidmatan pengguna berjalan pada PostgreSQL, dan jadual users mengandungi 200 juta baris. username TEXT NOT NULL mempunyai indeks unik. Setiap permintaan dalam talian, tugas latar belakang, dan pengguna peristiwa (event consumer) sedang membaca dan menulisnya pada masa ini. Pasukan ingin menamakan semula medan tersebut kepada handle; semasa migrasi, kedua-dua lajur mewakili nilai perniagaan yang sama persis.
Perkhidmatan ini mempunyai 80 tika aplikasi, dan penggunaan berperingkat mengambil masa 30 minit. Pekerja latar belakang (background workers) mungkin dimulakan semula lebih lewat daripada tika web. Trafik biasa tidak boleh dijeda, dan tiada tetingkap penyelenggaraan. SLO sedia ada kekal berkuat kuasa: migrasi mesti diperlahankan (throttle) atau dihentikan jika p99 penulisan, menunggu kunci (lock waits), kelewatan replikasi (replication lag), atau beban pangkalan data melepasi ambang pengeluaran. Matlamatnya adalah untuk menyelesaikan penamaan semula sambil memberikan setiap fasa invarian, get masuk (entry gate), get keluar (exit gate), dan laluan pembalikan yang eksplisit.
200 juta baris, 80 tika, dan pelancaran 30 minit ialah andaian temu duga. "Sifar masa henti" bermaksud tiada gangguan terancang sambil melindungi SLO sedia ada; ia tidak bermakna mengabaikan kunci pendek, percubaan yang gagal, atau pendikit (throttling). Kemahiran teras ialah membahagikan perubahan pangkalan data kepada beberapa keluaran yang serasi ke hadapan dan ke belakang, jadi ini ialah soalan bahagian belakang (backend). Pemecahan (sharding), migrasi rentas pangkalan data, dan konflik berbilang utama berada di luar skop pusingan pertama.
Perkara yang Dinilai oleh Penemu Duga
Isyarat pertama ialah sama ada calon mengenali masalah keserasian. Jika pasukan secara langsung menjalankan RENAME COLUMN username TO handle, tika lama masih menangani username manakala tika baharu hanya mengetahui handle. Sekurang-kurangnya satu versi akan gagal semasa tetingkap versi bercampur 30 minit. Penyata pangkalan data yang pantas tidak menjadikan pelancaran aplikasi sifar masa henti.
Isyarat kedua ialah memisahkan migrasi skema, migrasi data, dan peralihan kod. Reka bentuk yang selamat biasanya mengikut corak kembang-dan-kecut (expand-and-contract): tambah struktur yang boleh diabaikan oleh kod lama, gunakan kod yang serasi, isi semula dan sahkan secara berkelompok, tukar pembacaan dan penulisan, dan hanya selepas itu buang struktur lama. Setiap langkah harus boleh digunakan secara bebas, boleh diperhatikan, dan boleh dicuba semula. Kemas kini 200 juta baris dan DDL yang merosakkan tidak sepatutnya berada dalam satu transaksi penggunaan.
Isyarat ketiga ialah memahami sempadan kunci dan imbasan PostgreSQL. Subperintah ALTER TABLE yang berbeza memerlukan kunci yang berbeza, dan PostgreSQL mengambil ACCESS EXCLUSIVE melainkan dokumentasi menyatakan sebaliknya. Menambah lajur yang boleh bernilai nol (nullable) tanpa lalai tidak menulis semula jadual, tetapi ia masih memerlukan kunci. Jika permintaan kunci tersebut beratur di belakang transaksi yang panjang, permintaan terkemudian boleh beratur di belakangnya. NOT VALID, VALIDATE CONSTRAINT, dan CREATE INDEX CONCURRENTLY mengurangkan kesan ke atas penulisan serentak, tetapi masing-masing mempunyai tingkah laku kunci, beban, dan pemulihan kegagalan yang berbeza.
Akhir sekali, penemu duga mencari get berasaskan invarian. Jawapan yang kukuh melakukan lebih daripada sekadar menyenaraikan "tambah lajur, dwi-tulis, isi semula, gugurkan lajur." Ia menerangkan masa setiap penulis serasi, cara penulisan yang terlepas dikesan, mengapa pengisian semula adalah idempoten, bila membaca lajur baharu sahaja menjadi selamat, apa yang boleh dikembalikan oleh setiap fasa, dan bila lajur lama berhenti menjadi laluan pemulihan yang praktikal.
Soalan Penjelasan
- Di manakah semua penulis berada? Buat inventori perkhidmatan web, pekerja (workers), tugas berjadual, skrip pentadbiran, fungsi pangkalan data, pencetus (triggers), CDC, ETL, pertanyaan BI, paparan (views), dan integrasi luaran. Satu penulis yang tidak dinaik taraf boleh terus mewujudkan ketidakkonsistenan.
- Adakah lajur mesti kekal sama persis semasa migrasi? Dalam masalah ini, ya: ia adalah penamaan semula tulen. Jika
handlejuga memperkenalkan penormalan, peraturan huruf besar/kecil baharu, atau nilai yang dipilih pengguna, pengendalian konflik menjadi masalah migrasi data yang berbeza. - Bagaimanakah keunikan
usernamedilaksanakan? Lajur baharu memerlukan indeks atau kekangan unik yang setara. Sahkan bahawa kepekaan huruf besar/kecil, collation, tingkah laku nol, dan sebarang predikat separa tidak berubah. - Bolehkah perubahan aplikasi dan pangkalan data dihantar secara berasingan? Ia mesti berasingan. Jika skema dan aplikasi hanya boleh digunakan sebagai satu operasi yang tidak boleh dibahagikan, pasukan tidak boleh maju melalui beberapa fasa keserasian.
- Berapa lamakah migrasi boleh berjalan? Mengisi semula 200 juta baris mungkin mengambil masa berjam-jam atau berhari-hari. Reka bentuk ini memerlukan dasar jeda, sambung semula, penyiapan, dan pengekalan lajur lama yang bertahan melalui pelbagai keluaran.
- Apakah maksud pembalikan (rollback)? Membalikkan kod aplikasi, menghentikan pengisian semula, memulihkan penulisan lajur lama, dan memulihkan lajur yang digugurkan ialah empat operasi yang berbeza. Pembalikan aplikasi biasa tidak lagi selamat selepas lajur lama dialih keluar.
Jawapan 30 Saat
"Saya tidak akan menamakan semula di tempat yang sama (in place). Saya akan menggunakan expand-and-contract. Mula-mula tambah handle yang boleh bernilai nol dengan lock_timeout yang pendek; jika kunci tidak tersedia, gagalkan dan cuba semula. Keluaran keserasian A masih membaca username tetapi menulis kedua-dua lajur secara atomik. Selepas kesemua 80 tika dan setiap pekerja dinaik taraf, isi semula baris dengan handle IS NULL dalam kelompok kunci utama yang kecil dan idempoten. Pantau nilai nol, ketidakpadanan, ralat penulisan, kunci, p99, kelewatan replikasi, WAL, dan autovacuum sepanjang proses. Selepas pengisian semula, bina indeks unik baharu secara serentak, tambah semakan NOT VALID, sahkan ia secara berasingan, dan kemudian tetapkan NOT NULL. Keluaran B mengutamakan handle dengan sandaran username dan mengekalkan penulisan dwi. Selepas pemerhatian, baca handle sahaja, kemudian hentikan penulisan lajur lama. Kekalkan lajur lama sepanjang tetingkap pembalikan penuh dan gugurkannya hanya selepas kod, tugas, paparan, dan pengguna tidak lagi merujuknya. Get yang gagal membiarkan sistem dalam fasa serasi semasanya; pengguguran lajur tidak dianggap sebagai titik pembalikan biasa."
Penyelesaian Langkah Demi Langkah
Tentukan Invarian dan Get Migrasi Terlebih Dahulu
Sebelum melaksanakan DDL, tulis empat invarian:
- Semasa versi bercampur,
usernamekekal sebagai punca kebenaran (source of truth) pembalikan.handlemungkin bernilai nol, tetapi nilai bukan nol mesti sama denganusername. - Selepas keluaran keserasian mencapai setiap penulis, setiap penulisan baharu mesti mengemas kini kedua-dua lajur dalam satu transaksi. Satu lajur tidak boleh berjaya tanpa yang satu lagi.
- Pembacaan tidak boleh diputuskan daripada lajur lama sehingga kiraan ketidakpadanan nol dan bukan nol adalah sifar, semua penulis serasi, dan indeks serta kekangan baharu adalah sah.
- Pengecutan skema tidak boleh dimulakan sehingga kod pengeluaran, tugas latar belakang, paparan, laporan, CDC, dan binaan pembalikan tidak lagi memerlukan
username.
Rekodkan versi penggunaan, masa mula, pemilik, kursor kemajuan, papan pemuka, dan syarat keluar untuk setiap fasa. Pelaksana migrasi harus memegang pajakan (lease) atau kunci nasihat (advisory lock) PostgreSQL supaya dua pelaksana tidak dapat memajukan langkah yang sama secara serentak. Setiap langkah juga memerlukan versi unik dan rekod kejayaan tahan lama, membolehkan permulaan semula menyambung dan bukannya memainkan semula keseluruhan migrasi.
Fasa Satu: Kembangkan Skema Tanpa Mengubah Tingkah Laku
Latih DDL terhadap salinan bersaiz pengeluaran dan periksa transaksi panjang, giliran kunci, dan ruang cakera yang mencukupi. Tambah lajur yang boleh bernilai nol tanpa lalai:
BEGIN;
SET LOCAL lock_timeout = '2s';
ALTER TABLE users ADD COLUMN handle text;
COMMIT;Lajur yang boleh bernilai nol tanpa lalai tidak menulis semula 200 juta baris, tetapi ALTER TABLE masih memerlukan kunci yang kuat. lock_timeout menggagalkan percubaan yang tidak dapat memperoleh kunci dengan cepat, membolehkan sistem penggunaan mencuba semula kemudian dengan jitter. Kenal pasti transaksi panjang yang tidak normal sebelum pelaksanaan dan perhatikan siapa yang menyekat siapa semasa pelaksanaan. Menunggu selama-lamanya adalah tidak selamat kerana kunci kuat yang beratur boleh menyebabkan permintaan jadual terkemudian bertimbun di belakangnya.
Aplikasi lama mengabaikan handle selepas langkah ini, jadi pembalikan aplikasi kekal bebas. Jangan gabungkan penambahan tersebut dengan NOT NULL, lalai yang meruap, kekangan unik, dan kemas kini penuh. Tindakan itu akan menggabungkan perubahan metadata, imbasan jadual, pembinaan indeks, dan amplifikasi penulisan data ke dalam satu operasi berisiko tinggi.
Fasa Dua: Gunakan Penulis yang Serasi Semasa Lajur Lama Kekal Sebagai Punca Pembacaan
Keluaran A berkelakuan seperti berikut:
- Pembacaan terus menggunakan
usernamesahaja, jadi tingkah laku yang boleh dilihat oleh pengguna tidak berubah. - Penciptaan dan kemas kini pengguna menulis nilai yang sama pada
usernamedanhandledalam satu transaksi SQL. - Kegagalan pada salah satu lajur membalikkan keseluruhan transaksi; penulisan dwi bukanlah dua permintaan tak segerak.
- Metrik merekodkan percubaan penulisan dwi, kegagalan, dan ketidakpadanan tanpa mengelog nama pengguna sebenar.
Semasa pelancaran keluaran A, tika yang belum dinaik taraf masih menulis username sahaja, jadi baris handle IS NULL baharu adalah sah buat sementara waktu. Pengecualian tersebut ditutup hanya selepas kesemua 80 tika web, pekerja, tugas berjadual, dan pengguna bebas melaporkan versi yang serasi. Jika pasukan tidak dapat memastikan setiap penulis—contohnya, atur cara pihak ketiga menulis terus ke pangkalan data—pencetus pangkalan data sementara boleh menyegerakkan lajur tersebut. Imbal balasnya ialah tingkah laku penulisan yang tersembunyi, kos tambahan, dan replikasi, CDC, serta diagnosis insiden yang lebih kompleks. Anggap pencetus sedemikian sebagai infrastruktur migrasi dengan tarikh pengalihan keluar.
Fasa Tiga: Isi Semula Secara Idempoten mengikut Julat Kunci Utama
Mulakan migrasi latar belakang hanya selepas setiap penulis serasi. Gunakan julat set kunci (keyset ranges) kunci utama dan bukannya OFFSET, dan kekalkan setiap kelompok dalam transaksi pendek:
UPDATE users
SET handle = username
WHERE id > $1
AND id <= $2
AND handle IS NULL;Predikat handle IS NULL menjadikan kelompok selamat untuk dicuba semula dan mengelakkan penulisan ganti ke atas nilai yang telah ditulis oleh permintaan dalam talian. Simpan julat kunci utama terakhir yang telah selesai. Pelaksana boleh berhenti selepas mana-mana kelompok dan menyambung dari julat terakhir yang disahkan selepas dimulakan semula. Mulakan dengan seorang pekerja, kemudian sesuaikan saiz kelompok dan kelewatan daripada pengukuran tanpa menjanjikan daya pemprosesan tetap terlebih dahulu.
Selepas setiap kelompok, perhatikan p99 penulisan, CPU pangkalan data, menunggu kunci, kelewatan replikasi, WAL, cakera, tupel mati (dead tuples), dan autovacuum. Kurangkan saiz kelompok atau jeda sebaik sahaja sebarang ukuran menghampiri ambang pengeluarannya. Objektifnya ialah penyiapan yang stabil dalam lingkungan SLO. Transaksi 200 juta baris tunggal adalah tidak wajar semata-mata kerana skripnya lebih pendek.
Jalankan dua pengesahan bebas pada masa yang sama:
SELECT count(*) FROM users WHERE handle IS NULL;
SELECT count(*)
FROM users
WHERE handle IS DISTINCT FROM username;Kiraan pertama sepatutnya menurun secara berterusan kepada sifar. Yang kedua menggunakan IS DISTINCT FROM untuk menangkap kedua-dua perbezaan nol dan nilai bukan nol yang tidak sama. Sebarang hasil bukan sifar akan menyekat peralihan dan disiasat mengikut julat kunci utama. Pengisian semula tidak boleh menulis ganti konflik bukan nol secara senyap kerana itu boleh menyembunyikan penulis lama atau logik baharu yang salah yang masih aktif.
Fasa Empat: Tambah Indeks dan Kekangan
Oleh kerana username adalah unik, lajur baharu memerlukan indeks unik yang setara. Selepas pengisian semula dan pengesahan duplikasi, laksanakan ini di luar blok transaksi:
CREATE UNIQUE INDEX CONCURRENTLY users_handle_key
ON users (handle);Pembinaan serentak membolehkan penulisan biasa diteruskan, tetapi ia melakukan lebih banyak kerja, mengimbas jadual dua kali, dan menunggu transaksi yang berkaitan. Ia masih menggunakan CPU dan I/O. Pembinaan yang gagal boleh meninggalkan indeks INVALID. Pemulihan mesti memeriksa katalog, mengalih keluar artifak yang gagal, dan mencuba semula selepas membetulkan puncanya; kegagalan perintah sahaja tidak membuktikan bahawa pangkalan data kembali ke keadaan asalnya.
Wujudkan sifat bukan nol secara berfasa juga:
ALTER TABLE users
ADD CONSTRAINT users_handle_not_null
CHECK (handle IS NOT NULL) NOT VALID;
ALTER TABLE users
VALIDATE CONSTRAINT users_handle_not_null;
ALTER TABLE users
ALTER COLUMN handle SET NOT NULL;
ALTER TABLE users
DROP CONSTRAINT users_handle_not_null;NOT VALID mula menguatkuasakan semakan untuk penulisan terkemudian tanpa mengimbas baris lama serta-merta. VALIDATE CONSTRAINT kemudiannya menyemak baris sedia ada dengan tahap kunci yang lebih rendah. CHECK yang sah membuktikan tiada nilai nol, membolehkan SET NOT NULL terkemudian melangkau imbasan jadual penuh biasanya. Setiap penyata DDL masih mendapat masa menunggu kunci yang pendek, langkah pelaksanaan yang berasingan, dan pemantauan pengeluaran. "Serentak" dan "tiada penulisan semula" tidak bermakna "percuma".
Fasa Lima: Alihkan Pembacaan, Kemudian Hentikan Penulisan Lajur Lama
Keluaran B mengutamakan handle, bersandarkan pada username apabila bernilai nol, dan meneruskan penulisan dwi secara atomik. Get menyatakan nilai nol sepatutnya sudah sifar, tetapi sandaran mengekalkan keserasian untuk pembalikan dan mengasingkan data yang tidak dijangka. Mulakan dengan canary, kembangkan secara beransur-ansur, dan bandingkan hasil lajur baharu dan lajur lama, ralat, serta metrik perniagaan.
Selepas tetingkap pemerhatian, keluaran C membaca handle sahaja sambil terus menulis kedua-dua lajur. Masalah laluan bacaan masih boleh dibalikkan kepada B atau A kerana username kekal terkini. Hanya selepas tempoh pemerhatian yang meliputi tugas latar belakang, titik akhir (endpoints) frekuensi rendah, dan kitaran penggunaan lengkap, barulah keluaran D menghentikan penulisan username.
Menghentikan penulisan lajur lama mengubah semantik pembalikan. Pembalikan terkemudian kepada binaan yang hanya mengetahui username terlebih dahulu memerlukan pemulihan penulisan dwi dan pengisian semula secara terbalik bagi nilai yang dicipta semasa jurang tersebut. Membalikkan aplikasi secara langsung akan mendedahkan data lapuk. Letakkan keperluan ini dalam runbook dan get penggunaan supaya pengendalian insiden tidak bergantung pada jurutera yang mengingatinya.
Fasa Enam: Tangguhkan Pengecutan
Sebelum pengalihan keluar, gunakan carian kod, log pertanyaan, katalog kebergantungan, dan inventori pengguna untuk membuktikan bahawa username tidak mempunyai pembaca. Alih keluar indeks lama, kekangan, pencetus, dan kebergantungan paparan terlebih dahulu, kemudian gugurkan lajur dalam keluaran berasingan:
ALTER TABLE users DROP COLUMN username;Menggugurkan lajur melintasi sempadan yang merosakkan. Walaupun PostgreSQL tidak menulis semula jadual serta-merta, aplikasi lama, cache skema, paparan, dan pertanyaan luaran boleh gagal serta-merta. Data yang dialih keluar juga tidak tersedia untuk pembalikan aplikasi biasa. Pengguguran harus berlaku sekurang-kurangnya satu tetingkap pengekalan pembalikan penuh selepas peralihan baca dan tulis, secara berasingan daripada keluaran kod yang berhenti menggunakan lajur tersebut. Sandaran ialah pemulihan bencana, bukan pembalikan penggunaan berkependaman rendah.
Contoh Jawapan yang Kukuh
"Risiko utama ialah keserasian semasa penggunaan berperingkat selama 30 minit. Saya akan membahagikan perubahan kepada pengembangan, penulisan serasi, pengisian semula dan pengesahan, peralihan bacaan, dan pengecutan tertangguh.
Mula-mula saya menambah handle yang boleh bernilai nol dengan lock_timeout yang pendek; jika kunci tidak tersedia, percubaan gagal dan mencuba semula. Lajur tanpa lalai yang boleh bernilai nol tidak menulis semula jadual, tetapi DDL masih mengambil kunci yang kuat, jadi saya memeriksa transaksi panjang dan giliran kunci. Keluaran A masih membaca username, dan setiap penulis mengemas kini kedua-dua lajur dalam satu transaksi pangkalan data. Pengisian semula bermula hanya selepas kesemua 80 tika, pekerja, dan pengguna telah dinaik taraf.
Pengisian semula menggunakan transaksi julat kunci utama yang pendek dengan UPDATE ... WHERE handle IS NULL, mengekalkan kemajuan, dan selamat untuk dicuba semula. Kadarnya mengikut p99 pengeluaran, kelewatan replikasi, WAL, tupel mati, dan autovacuum. Kiraan nol mesti mencapai sifar, dan handle IS DISTINCT FROM username mesti kekal sifar. Konflik bukan nol disiasat dan bukannya ditulis ganti.
Selepas get data, saya membina indeks unik yang setara dengan CREATE UNIQUE INDEX CONCURRENTLY dan mengendalikan sebarang saki-baki indeks tidak sah selepas kegagalan. Saya menambah CHECK ... NOT VALID, mengesahkannya secara berasingan, dan kemudian menetapkan NOT NULL. Keluaran B mengutamakan lajur baharu dengan sandaran lajur lama dan mengekalkan penulisan dwi. Keluaran C membaca lajur baharu sahaja tetapi masih dwi-tulis. Keluaran D menghentikan penulisan lajur lama hanya selepas kitaran pemerhatian penuh.
Setiap fasa mempunyai laluan pembalikan. Sebelum peralihan bacaan, saya boleh membalikkan aplikasi secara langsung. Semasa membaca lajur baharu tetapi masih melakukan penulisan dwi, saya boleh kembali kepada pembacaan lama. Selepas penulisan lama berhenti, saya mesti memulihkan penulisan dwi dan mengisi semula secara terbalik sebelum aplikasi lama selamat digunakan. Akhir sekali, selepas kod, tugas, paparan, CDC, dan laporan tidak lagi merujuk username dan tetingkap pembalikan telah berlalu, saya menggugurkannya dalam keluaran berasingan. Get yang gagal membiarkan sistem dalam keadaan serasi dan bukannya mara ke pengecutan yang merosakkan."
Kesilapan Biasa
- Menamakan semula lajur di tempat yang sama → Tika lama dan baharu memerlukan nama yang berbeza semasa pelancaran → Gunakan lajur baharu dan berbilang keluaran yang serasi.
- Mengemas kini 200 juta baris dalam satu transaksi → Transaksi ini menguatkan WAL, kunci, kelewatan replikasi, kekembungan (bloat), dan masa pemulihan → Gunakan kelompok julat kunci utama yang pendek dan idempoten.
- Memulakan pengisian semula sebaik sahaja penulisan dwi bermula → Tika yang belum dinaik taraf masih boleh mencipta nilai nol baharu → Tunggu sehingga setiap penulis serasi sebelum menjadikan sifar nol sebagai get.
- Melaksanakan penulisan dwi sebagai dua permintaan → Tamat masa boleh mengemas kini satu lajur sahaja → Kemas kini kedua-duanya secara atomik dalam satu transaksi pangkalan data.
- Hanya menyemak
handle IS NULL→ Nilai bukan nol yang tidak sama terlepas daripada pengesanan → Semak jugaIS DISTINCT FROMdan siasat konflik. - Menganggap
ADD COLUMNbebas kunci → DDL metadata masih memerlukan kunci jadual, dan permintaan DDL yang beratur boleh membesarkan penyekatan → Gunakan masa menunggu kunci yang pendek, percubaan semula, dan pemantauan kunci/transaksi. - Membina indeks unik secara normal → Pembinaan indeks jadual besar boleh menyekat penulis untuk tempoh yang tidak boleh diterima → Gunakan
CONCURRENTLYdan kendalikan beban tambahan serta pemulihan indeks tidak sah. - Menggugurkan lajur lama serta-merta selepas pengisian semula → Pekerja frekuensi rendah, paparan, cache skema, atau binaan pembalikan mungkin masih memerlukannya → Tangguhkan pengecutan merentasi tetingkap pemerhatian dan pembalikan yang lengkap.
- Menganggap sandaran sebagai butang pembalikan → Memulihkan pangkalan data 200 juta baris adalah lebih perlahan dan lebih berisiko daripada pembalikan aplikasi → Kekalkan struktur yang serasi dalam talian sehingga ke sempadan pemusnahan.
- Menjanjikan "migrasi sifar kesan" → DDL, indeks, dan pengisian semula semuanya menggunakan kunci atau sumber → Janjikan tiada gangguan terancang, lindungi SLO, dan jeda sebelum ambang dilepasi.
Soalan Susulan
Mengapa tidak menambah handle dengan nilai lalai?
PostgreSQL boleh mengelakkan penulisan semula jadual untuk nilai lalai pemalar yang tidak meruap, tetapi tiada pemalar yang menyatakan "salin username sedia ada bagi baris ini." Walaupun nilai lalai pantas secara fizikal, ia masih memerlukan kunci DDL dan tidak menyelesaikan masalah tika lama yang hanya menulis lajur lama. Migrasi ini masih memerlukan penulis yang serasi dan pengisian semula data. Sama ada sisipan masa hadapan memerlukan nilai lalai ialah keputusan semantik perniagaan, bukan pengganti kepada pelan pelancaran.
Bagaimana jika handle mesti ditukar kepada huruf kecil dan dijadikan unik semula?
Itu bukan lagi penamaan semula tulen. Tentukan satu fungsi penormalan dan dasar konflik, kemudian kira pertindihan dalam lower(username) pada replika atau tugas luar talian. Tentukan sama ada untuk mengekalkan nilai, menambah akhiran, atau memerlukan tindakan pengguna. Simpan nilai asal dan status penukaran semasa pengisian semula, dan cipta indeks unik hanya selepas konflik mencapai sifar. Penulisan dalam talian dan pengisian semula mesti menggunakan pelaksanaan penormalan yang sama.
Bagaimana jika semua penulis tidak boleh dinaik taraf bersama?
Bagi sistem luaran yang tidak dapat berhijrah dengan cepat, tambah pencetus pangkalan data sementara yang menyalin penulisan lajur lama ke lajur baharu dan merekodkan penggunaan supaya pemanggil yang tinggal dapat ditemui. Pencetus harus menolak permintaan yang memberikan nilai bercanggah. Nilaikan rekursi, replikasi, dan tingkah laku CDC. Sebaik sahaja setiap pemanggil telah bermigrasi, lumpuhkan dan perhatikan sebelum mengalih keluar pencetus supaya logik perniagaan yang tersembunyi tidak menjadi kekal.
Bagaimana jika kelewatan replikasi terus meningkat semasa pengisian semula?
Jedakan kelompok baharu dan biarkan replika mengejar ketinggalan dan bukannya menambah pekerja untuk mengejar kemajuan. Periksa saiz kelompok, irama komit (commit cadence), kadar WAL, pertanyaan panjang, dan autovacuum. Sambung semula dengan kelompok yang lebih kecil dan kurang keserentakan. Jika pembacaan bergantung pada replika, kelewatan replikasi sudah menjadi risiko yang boleh dilihat oleh pengguna; tarikh penyiapan pengisian semula adalah tertakluk kepada SLO pengeluaran.
Bolehkah CREATE UNIQUE INDEX CONCURRENTLY dijalankan semula secara terus selepas kegagalan?
Jangan jalankan semula secara membabi buta. Indeks tidak sah dengan nama yang sama mungkin kekal dalam katalog, dan binaan unik serentak mungkin telah menguatkuasakan keunikan terhadap transaksi lain semasa fasa yang gagal. Periksa kesahihan indeks, kenal pasti kegagalan data atau sumber, alih keluar indeks yang gagal mengikut runbook, dan kemudian bina semula. Perintah itu juga tidak boleh berjalan di dalam blok transaksi biasa, jadi alat migrasi mesti menyokong mod pelaksanaan tersebut.
Fasa manakah yang paling sukar untuk dibalikkan?
Selepas penulisan lajur lama berhenti, nilai lama mula ketinggalan. Selepas lajur lama digugurkan, kedua-dua data dan skema melintasi sempadan yang merosakkan. Yang pertama memerlukan pemulihan penulisan dwi dan pengisian semula secara terbalik sebelum binaan lama selamat. Yang kedua biasanya memerlukan pembaikan ke hadapan atau pemulihan sandaran. Simpan tindakan ini dalam keluaran berasingan dan pastikan lajur lama sentiasa dikemas kini untuk tetingkap pemerhatian yang cukup lama.