Masalah dan konteks
Sebuah sistem menyimpan pemesanan ruangan dan detailnya. Alur lama memeriksa konflik di aplikasi sebelum melakukan insert, tetapi permintaan yang bersamaan masih dapat membuat tumpang tindih. Gunakan temporal constraints PostgreSQL 18 untuk menegakkan non-overlap di database dan memungkinkan tabel anak merujuk ke periode validitas yang dicakup oleh induknya.
Hal yang dievaluasi pewawancara
Kuncinya adalah bahwa WITHOUT OVERLAPS berada pada kolom rentang terakhir dari primary-key atau unique constraint, sedangkan PERIOD berada pada temporal foreign key. Untuk prefix keys yang sama, rentang yang tidak kosong membentuk himpunan yang tidak tumpang tindih. Jelaskan batas half-open, rentang kosong, NULL, pembaruan, migrasi data kotor, dan konflik konkuren.
Pertanyaan klarifikasi untuk diajukan terlebih dahulu
Model waktu
Tanyakan apakah skema menggunakan tstzrange atau daterange, zona waktu mana yang berlaku, dan apakah rentang bersifat half-open. Aturan endpoint dan kedekatan menentukan hasil batasan secara langsung.
Kunci bisnis dan referensi
Konfirmasikan ID ruangan sebagai prefix bisnis, apakah periode detail harus dicakup sepenuhnya oleh periode induk, dan apakah satu pemesanan dapat mencakup beberapa versi.
Migrasi dan konkurensi
Tanyakan apakah baris lawas berisi tumpang tindih atau rentang kosong, jendela migrasi, dan strategi rollback. Insert konkuren harus bergantung pada batasan database dan penanganan kesalahan transaksi, bukan hanya kunci aplikasi.
Kerangka jawaban 30 detik
“Saya menempatkan room_id di awal dan rentang validitas di akhir, menggunakan PRIMARY KEY (room_id, during WITHOUT OVERLAPS) untuk mencegah tumpang tindih untuk satu ruangan. Tabel detail menggunakan FOREIGN KEY (room_id, PERIOD during) untuk merujuk ke temporal key. Saya membersihkan tumpang tindih dan rentang kosong sebelum menambahkan batasan secara bertahap; konflik konkuren menjadi kesalahan database yang dicoba kembali atau dilaporkan oleh transaksi, dengan aturan half-open dan zona waktu yang eksplisit.”
Langkah-langkah solusi terperinci
Langkah 1: Pilih tipe rentang dan batas
Gunakan tipe rentang diskrit atau kontinu yang sesuai dengan bisnis dan standarkan interval half-open. Tolak rentang kosong, tentukan kedekatan, dan normalisasikan zona waktu agar transisi waktu musim panas tidak membuat tumpang tindih yang tidak disengaja.
Langkah 2: Tentukan temporal primary key
Tempatkan kolom identitas terlebih dahulu dan kolom rentang terakhir, lalu gunakan WITHOUT OVERLAPS. Ini menyatakan non-overlap dalam satu prefiks entitas sambil mempertahankan identitas primary-key dan semantik non-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 period foreign key
Ketika detail juga memiliki periode, gunakan PERIOD untuk merujuk ke temporal primary atau unique constraint. Konfirmasikan bahwa cakupan penuh diperlukan dan uji pemisahan atau pemendekan periode 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 historis
Sebelum peluncuran, temukan tumpang tindih, rentang kosong, NULL, dan endpoint tidak valid per ruangan, lalu pilih kebijakan penggabungan, pemisahan, atau pembatalan. Validasi pada shadow table dan perbaiki secara bertahap untuk menghindari penguncian tabel besar sekaligus.
Langkah 5: Tangani penulisan bersamaan
Jika dua transaksi memasukkan periode yang tumpang tindih untuk satu ruangan, biarkan database yang menengahi. Aplikasi menangkap kesalahan batasan, membaca ulang ketersediaan, dan mencoba kembali atau mengembalikan konflik yang jelas. Alur periksa-lalu-insert tidak cukup, dan kunci global yang tidak terkontrol bukanlah pengganti.
Langkah 6: Evaluasi semantik pembaruan dan penghapusan
Periode yang diperbarui dapat berkonflik dengan dirinya sendiri atau baris lain, sehingga pemisahan pemesanan dilakukan dalam satu transaksi. Sebelum menghapus atau memperpendek periode induk, verifikasi tindakan temporal-foreign-key untuk menghindari detail yatim atau perluasan cakupan secara diam-diam.
Langkah 7: Verifikasi kueri dan operasi
Uji kasus berdekatan, mengandung, identik, kosong, lintas zona waktu, dan batas presisi. Pantau tingkat kesalahan batasan, waktu tunggu kunci migrasi, dan ukuran indeks; batasi percobaan ulang penulisan untuk mencegah badai percobaan ulang akibat persaingan tinggi.
Contoh jawaban berkualitas tinggi
Saya akan memilih tstzrange dengan konvensi half-open, mendefinisikan (room_id, during WITHOUT OVERLAPS) sebagai primary key, dan menggunakan (room_id, PERIOD during) untuk foreign key detail yang periodenya harus dicakup oleh induk. Saya akan membersihkan tumpang tindih lawas dan endpoint yang tidak valid terlebih dahulu. Insert konkuren mengandalkan batasan database; aplikasi menangkap konflik dan mencoba kembali atau mengembalikan ketersediaan. Pengujian mencakup kedekatan, tumpang tindih, pemisahan induk, konversi zona waktu, dan persaingan tinggi.
Kesalahan umum
- Kesalahan: Hanya memeriksa sebelum memasukkan di aplikasi. → Alasan: Transaksi konkuren dapat lolos pemeriksaan bersama-sama. → Solusi: Gunakan temporal constraint sebagai penentu akhir.
- Kesalahan: Menempatkan kolom rentang sebelum kunci. → Alasan: Sintaks dan semantik prefiks mengharuskan rentang berada di akhir. → Solusi: Daftarkan kunci bisnis terlebih dahulu, lalu
WITHOUT OVERLAPS. - Kesalahan: Mengasumsikan rentang yang berdekatan selalu berkonflik. → Alasan: Semantik batas menentukan hasilnya. → Solusi: Standarkan rentang half-open dan uji endpoint.
- Kesalahan: Mengaktifkan batasan secara langsung selama migrasi. → Alasan: Tumpang tindih historis atau rentang kosong menyebabkan kegagalan dan penguncian lama. → Solusi: Audit dan perbaiki terlebih dahulu, lalu lakukan peluncuran bertahap.
Pertanyaan lanjutan dan jawaban
Pertanyaan lanjutan 1: Apakah [10:00, 11:00) dan [11:00, 12:00) berkonflik?
Di bawah konvensi half-open yang konsisten mereka tidak berkonflik, karena 11:00 hanya milik rentang kedua. Batas tertutup atau campuran memerlukan aturan bisnis yang eksplisit sebelum menentukan batasan.
Pertanyaan lanjutan 2: Mengapa kolom rentang harus menjadi yang terakhir?
Temporal key mengelompokkan baris berdasarkan kolom prefiks dan kemudian mengharuskan rentang akhir tidak tumpang tindih. Menempatkan rentang terlebih dahulu tidak dapat mengekspresikan pengelompokan entitas yang sama.
Pertanyaan lanjutan 3: Apakah period foreign key hanya memeriksa satu saat?
Tidak. PERIOD menyatakan bahwa periode yang dirujuk harus dicakup oleh periode induk. Konfirmasikan kombinasi tepat dan batas terhadap semantik dan pengujian PostgreSQL 18; ini bukan point foreign key.
Pertanyaan lanjutan 4: Bagaimana Anda menghindari badai percobaan ulang di bawah persaingan?
Batasi percobaan ulang dan tambahkan jitter, baca ulang periode yang tersedia, lalu kembalikan konflik atau antrekan permintaan setelah batas tercapai. Pantau kesalahan batasan dan waktu tunggu kunci, dan lakukan sharding penulisan berdasarkan ruangan jika diperlukan.