Masalah dan konteks
Sistem menyimpan tempahan bilik dan butirannya. Aliran lama memeriksa konflik dalam aplikasi sebelum memasukkan data, tetapi permintaan serentak masih boleh mewujudkan pertindihan. Gunakan kekangan temporal PostgreSQL 18 untuk menguatkuasakan bukan pertindihan dalam pangkalan data dan membolehkan jadual anak merujuk kepada tempoh kesahihan yang diliputi oleh induk.
Perkara yang dinilai oleh penemu duga
Kuncinya ialah WITHOUT OVERLAPS kepunyaan lajur julat akhir bagi kekangan kunci utama atau unik, manakala PERIOD kepunyaan kunci asing temporal. Untuk kunci awalan yang sama, julat yang tidak kosong membentuk set yang tidak bertindih. Terangkan sempadan separa terbuka, julat kosong, NULL, kemas kini, migrasi data kotor dan konflik serentak.
Soalan penjelasan untuk ditanya terlebih dahulu
Model masa
Tanya sama ada skema menggunakan tstzrange atau daterange, zon masa mana yang terpakai, dan sama ada julat adalah separa terbuka. Peraturan titik akhir dan kedekatan menentukan hasil kekangan secara langsung.
Kunci perniagaan dan rujukan
Sahkan ID bilik sebagai awalan perniagaan, sama ada tempoh butiran mesti diliputi sepenuhnya oleh tempoh induk, dan sama ada satu tempahan boleh merangkumi beberapa versi.
Migrasi dan keserentakan
Tanya sama ada baris legasi mengandungi pertindihan atau julat kosong, tetingkap migrasi dan strategi pengunduran. Sisipan serentak mesti bergantung pada kekangan pangkalan data dan pengendalian ralat transaksi, bukan hanya kunci aplikasi.
Kerangka jawapan 30 saat
“Saya meletakkan room_id dahulu dan julat kesahihan di hujung, menggunakan PRIMARY KEY (room_id, during WITHOUT OVERLAPS) untuk menghalang pertindihan bagi satu bilik. Jadual butiran menggunakan FOREIGN KEY (room_id, PERIOD during) untuk merujuk kepada kunci temporal. Saya membersihkan pertindihan dan julat kosong sebelum menambah kekangan secara berperingkat; konflik serentak menjadi ralat pangkalan data yang dicuba semula atau dilaporkan oleh transaksi, dengan peraturan separa terbuka dan zon masa yang eksplisit.”
Langkah penyelesaian terperinci
Langkah 1: Pilih jenis julat dan sempadan
Gunakan jenis julat diskret atau berterusan yang sepadan dengan perniagaan dan standardkan selang separa terbuka. Tolak julat kosong, tentukan kedekatan, dan normalkan zon masa supaya peralihan waktu jimat siang tidak menghasilkan pertindihan yang tidak disengajakan.
Langkah 2: Tentukan kunci utama temporal
Letakkan lajur identiti dahulu dan lajur julat di hujung, kemudian gunakan WITHOUT OVERLAPS. Ini menyatakan bukan pertindihan dalam satu awalan entiti sambil mengekalkan identiti kunci utama dan semantik bukan null.
CREATE TABLE room_booking (
room_id bigint NOT NULL,
during tstzrange NOT NULL,
guest_id bigint NOT NULL,
PRIMARY KEY (room_id, during WITHOUT OVERLAPS)
);Langkah 3: Tentukan kunci asing tempoh
Apabila butiran juga mempunyai tempoh, gunakan PERIOD untuk merujuk kepada kekangan utama atau unik temporal. Sahkan bahawa liputan penuh diperlukan dan uji pemisahan atau pemendekan tempoh induk.
CREATE TABLE booking_charge (
room_id bigint NOT NULL,
during tstzrange NOT NULL,
amount numeric NOT NULL,
FOREIGN KEY (room_id, PERIOD during)
REFERENCES room_booking (room_id, PERIOD during)
);Langkah 4: Bersihkan data sejarah
Sebelum pelancaran, cari pertindihan, julat kosong, NULL dan titik akhir tidak sah bagi setiap bilik, kemudian pilih dasar gabung, pisah atau batalkan. Sahkan pada jadual bayangan dan baiki secara berkelompok untuk mengelakkan mengunci jadual besar sekaligus.
Langkah 5: Kendalikan penulisan serentak
Jika dua transaksi memasukkan tempoh yang bertindih untuk satu bilik, biarkan pangkalan data membuat keputusan. Aplikasi menangkap ralat kekangan, membaca semula ketersediaan, dan mencuba semula atau mengembalikan konflik yang jelas. Aliran semak-kemudian-masuk tidak mencukupi, dan kunci global yang tidak terkawal bukanlah pengganti.
Langkah 6: Nilaikan semantik kemas kini dan padam
Tempoh yang dikemas kini boleh berkonflik dengan dirinya sendiri atau baris lain, jadi pemisahan tempahan hendaklah dalam satu transaksi. Sebelum memadam atau memendekkan tempoh induk, sahkan tindakan kunci-asing-temporal untuk mengelakkan butiran yatim atau memperluas liputan secara senyap.
Langkah 7: Sahkan pertanyaan dan operasi
Uji kes bersebelahan, mengandungi, sama, kosong, merentasi zon masa dan sempadan ketepatan. Pantau kadar ralat kekangan, masa menunggu kunci migrasi dan saiz indeks; hadkan percubaan semula penulisan untuk mengelakkan ribut percubaan semula akibat persaingan tinggi.
Contoh jawapan berkualiti tinggi
Saya akan memilih tstzrange dengan konvensyen separa terbuka, menentukan (room_id, during WITHOUT OVERLAPS) sebagai kunci utama, dan menggunakan (room_id, PERIOD during) untuk kunci asing butiran yang tempohnya mesti diliputi oleh induk. Saya akan membersihkan pertindihan legasi dan titik akhir tidak sah terlebih dahulu. Sisipan serentak bergantung pada kekangan pangkalan data; aplikasi menangkap konflik dan mencuba semula atau mengembalikan ketersediaan. Ujian merangkumi kedekatan, pertindihan, pemisahan induk, penukaran zon masa dan persaingan tinggi.
Kesilapan biasa
- Kesilapan: Hanya menyemak sebelum memasukkan data dalam aplikasi. → Sebab: Transaksi serentak boleh melepasi semakan bersama-sama. → Penyelesaian: Gunakan kekangan temporal sebagai pemutus muktamad.
- Kesilapan: Meletakkan lajur julat sebelum kunci. → Sebab: Sintaks dan semantik awalan memerlukan julat di hujung. → Penyelesaian: Senaraikan kunci perniagaan dahulu, kemudian
WITHOUT OVERLAPS. - Kesilapan: Menganggap julat bersebelahan sentiasa berkonflik. → Sebab: Semantik sempadan menentukan hasilnya. → Penyelesaian: Standardkan julat separa terbuka dan uji titik akhir.
- Kesilapan: Mengaktifkan kekangan dengan serta-merta semasa migrasi. → Sebab: Pertindihan sejarah atau julat kosong menyebabkan kegagalan dan kunci yang panjang. → Penyelesaian: Audit dan baiki dahulu, kemudian lancarkan secara berperingkat.
Soalan susulan dan jawapan
Soalan susulan 1: Adakah [10:00, 11:00) dan [11:00, 12:00) berkonflik?
Di bawah konvensyen separa terbuka yang konsisten, ia tidak berkonflik, kerana 11:00 hanya kepunyaan julat kedua. Sempadan tertutup atau bercampur memerlukan peraturan perniagaan yang jelas sebelum menentukan kekangan.
Soalan susulan 2: Mengapakah lajur julat mesti berada di hujung?
Kunci temporal mengumpulkan baris mengikut lajur awalan dan kemudian memerlukan julat akhir tidak bertindih. Meletakkan julat dahulu tidak dapat menyatakan pengelompokan entiti yang sama.
Soalan susulan 3: Adakah kunci asing tempoh hanya menyemak satu detik?
Tidak. PERIOD menyatakan bahawa tempoh yang dirujuk mesti diliputi oleh tempoh induk. Sahkan gabungan dan sempadan yang tepat terhadap semantik dan ujian PostgreSQL 18; ia bukan kunci asing satu titik.
Soalan susulan 4: Bagaimanakah anda mengelakkan ribut percubaan semula di bawah persaingan?
Hadkan percubaan semula dan tambah jitter, baca semula tempoh yang tersedia, kemudian kembalikan konflik atau masukkan permintaan ke dalam giliran selepas had. Pantau ralat kekangan dan masa menunggu kunci, dan lakukan sharding penulisan mengikut bilik apabila perlu.