Soalan
Jadual PostgreSQL pengeluaran memerlukan CHECK atau kekangan kunci asing yang baharu. Baris sedia ada mungkin melanggarnya, dan perniagaan tidak boleh bertolak ansur dengan sekatan penulisan yang lama. Reka bentuk aliran daripada mencari pelanggaran, menambah kekangan NOT VALID, membaiki baris sejarah, dan menjalankan VALIDATE CONSTRAINT. Rangkumi kunci (locks), keserentakan, pemantauan dan pengendalian kegagalan.
Perkara yang diuji oleh penemu duga
- Sama ada anda membezakan tingkah laku kunci semasa menambah kekangan daripada imbasan pengesahan kemudian.
- Sama ada anda tahu bahawa
NOT VALIDmelangkau imbasan baris lama sementara sisipan dan kemas kini baharu masih diperiksa. - Sama ada anda menyelaraskan pembaikan, pengesahan, dan pelancaran aplikasi dan bukannya mengeluarkan satu DDL yang menyekat.
- Sama ada keadaan kekangan kekal kelihatan dan boleh dipulihkan melalui kegagalan pengesahan, transaksi yang panjang, dan pengembalian semula (rollback).
Jawapan model
Mulakan dengan pertanyaan baca sahaja untuk menganggarkan baris yang melanggar, ketersediaan indeks, dan transaksi yang panjang. Semasa tetingkap terkawal, jalankan ADD CONSTRAINT ... NOT VALID. Ia tidak mengimbas baris sedia ada, tetapi ia segera memeriksa sisipan dan kemas kini yang terkemudian; baris sejarah mungkin masih melanggar peraturan, jadi keadaannya secara eksplisit belum selesai pengesahan.
Baiki baris sejarah dalam kelompok terhad dengan sempadan komit dan rekod kemajuan. Logik pembaikan mesti sepadan dengan peraturan aplikasi, jadi gunakan kod yang serasi terlebih dahulu apabila perlu. Kemudian jalankan VALIDATE CONSTRAINT sambil memerhatikan masa menunggu kunci, tempoh imbasan, dan beban pangkalan data. Pengesahan yang berjaya menandakan kekangan katalog sah dan melengkapkan migrasi.
Untuk kunci asing, sahkan kekangan keunikan yang sesuai pada lajur yang dirujuk dan nilai operasi tulis dan padam yang serentak. Jika pengesahan gagal, kekalkan kekangan NOT VALID untuk melindungi penulisan baharu, baiki baris yang selebihnya, dan cuba semula. Gugurkannya (drop) hanya apabila keperluan tersebut benar-benar dialih keluar.
Aliran migrasi
-- 1. Record violations and create repair work
SELECT count(*) FROM orders WHERE total < 0;
-- 2. Add the constraint without scanning historical rows
ALTER TABLE orders
ADD CONSTRAINT orders_total_nonnegative
CHECK (total >= 0) NOT VALID;
-- 3. Repair in batches, then validate
ALTER TABLE orders
VALIDATE CONSTRAINT orders_total_nonnegative;Alat migrasi harus menyimpan nama kekangan, kursor kelompok, masa mula dan tamat, hasil pengesahan, dan pengendali. Sebelum pelancaran, periksa setiap laluan penulisan aplikasi terhadap peraturan yang sama supaya tugas pembaikan dan logik perniagaan tidak saling menulis ganti.
Nilai NOT VALID adalah memisahkan imbasan sejarah yang mahal daripada langkah menambah kekangan; pengesahan masih mengimbas jadual dan mengambil kunci yang didokumentasikan, jadi ia bukan percuma. Periksa transaksi yang panjang dan kelengahan replikasi, tetapkan had masa penyataan (statement timeout) dan amaran menunggu kunci, serta jalankan pengesahan dalam tetingkap terkawal.
Transaksi baharu diperiksa semasa pengesahan, manakala pembaikan sejarah mesti mengelak daripada menulis ganti kemas kini perniagaan. Gunakan julat indeks yang stabil dan transaksi pendek untuk kelompok. FOR UPDATE SKIP LOCKED boleh menuntut kerja apabila sesuai, tetapi baris yang dilangkau tidak boleh membuat metrik kemajuan kelihatan selesai.
Perangkap biasa
- Menganggap
NOT VALIDmenyahdayakan kekangan dan membenarkan penulisan kotor baharu. - Menjalankan
VALIDATE CONSTRAINTtanpa memeriksa transaksi yang panjang, masa menunggu kunci, dan kapasiti replikasi. - Membaiki setiap baris sejarah dalam satu transaksi besar, menyebabkan kembung (bloat), kunci yang panjang, dan pembalikan yang sukar.
- Memperbaiki CHECK sambil mengabaikan indeks yang dirujuk dan laluan pemadaman yang diperlukan oleh kunci asing.
- Menggugurkan kekangan yang gagal dan kehilangan perlindungan untuk penulisan baharu serta laluan pemulihan seterusnya.
Pengendalian kegagalan dan pengembalian semula
Gunakan keadaan yang eksplisit seperti planned, not_valid, backfilling, validating, validated, dan aborted. Kekalkan setiap peralihan dalam jadual migrasi dan log audit. Apabila pengesahan mendapati pelanggaran, rekod nama kekangan dan sampel kunci yang diredaksikan, jeda pengesahan, dan kekalkan kekangan; selepas pembaikan, sambung semula daripada kemajuan yang direkodkan.
Jika keluaran aplikasi mesti diundur semula, kod keserasian masih perlu mengendalikan kedua-dua baris lama dan kekangan baharu. Menggugurkan kekangan NOT VALID adalah jalan terakhir dan memerlukan pengesahan bahawa penulisan baharu tidak boleh mencipta semula masalah tersebut. Sebarang DROP CONSTRAINT harus mempunyai kelulusan, sandaran, dan rancangan penambahan semula.
Kebolehpemerhatian (Observability)
Pantau kiraan pelanggaran, kadar pembaikan, anggaran baki masa, kemajuan pengesahan, masa menunggu kunci, usia transaksi tertua, pertumbuhan WAL, dan kelengahan replikasi. Bezakan antara "penulisan baharu melanggar kekangan" daripada "baris sejarah tidak disahkan"; kedua-duanya memerlukan keutamaan tindak balas yang berbeza.
Selepas pengesahan, buat pertanyaan pada pg_constraint.convalidated dan nama kekangan untuk mengesahkan keadaan katalog. Simpan hasil, pelan pertanyaan, dan tetingkap beban dalam rekod migrasi. Laporan luaran harus menggunakan kunci yang diredaksikan dan data agregat, jangan sekali-kali meletakkan data perniagaan dalam log.
- PostgreSQL 17
ALTER TABLE: semantik kunci dan keserentakan untukNOT VALIDdanVALIDATE CONSTRAINT. - Dokumentasi kekangan PostgreSQL semasa: peraturan pengesahan CHECK, kunci asing, dan baris sejarah.
- PostgreSQL 17
pg_constraint: medan katalog seperticonvalidated.
Soalan susulan
Mengapakah penulisan baharu diperiksa sedangkan baris lama mungkin kekal tidak sah?
NOT VALID melangkau imbasan baris yang telah wujud semasa kekangan ditambah. Definisi tersebut masih digunakan serta-merta pada operasi INSERT dan UPDATE yang berikutnya, menghalang tunggakan sejarah daripada terus bertambah.
Bolehkah operasi menulis diteruskan semasa pengesahan?
Boleh, tetapi pengesahan membaca jadual dan mengambil kunci yang didokumentasikan, jadi masa menunggu dan beban mesti dikawal. Baris baharu diperiksa, dan kelompok pembaikan mesti mengelak daripada menulis ganti kemas kini aplikasi.
Bagaimanakah anda menganggarkan tempoh pengesahan?
Gunakan saiz jadual, pelan imbasan, tingkah laku cache, beban kerja serentak, dan tetingkap penyelenggaraan untuk anggaran yang diukur atau sampel. Jangan anggap kiraan baris sahaja adalah linear; tetapkan had masa tamat dan dasar pembatalan sebelum ke peringkat pengeluaran.
Apakah yang istimewa tentang migrasi kunci asing?
Sahkan keunikan dan pengindeksan pada lajur yang dirujuk dan tentukan semantik pemadaman yang stabil. Semasa pengesahan, perhatikan baris anak sedia ada bersama-sama dengan pemadaman, kemas kini, dan konflik kunci yang berlaku secara serentak.
Bilakah anda patut meninggalkan dan menggugurkan kekangan?
Hanya apabila keperluan ditarik balik atau direka bentuk secara salah dan perlindungan alternatif wujud. Kegagalan pengesahan semata-mata bukanlah sebab untuk menggugurkannya; mengekalkan NOT VALID terus melindungi data baharu dan memelihara laluan pemulihan.