Chống trùng lịch đặt sân bằng PostgreSQL: dùng exclusion constraint
Thiết kế chống chồng lấn lịch đặt sân bằng PostgreSQL, với ví dụ SQL đa tenant, trạng thái giữ chỗ và các tình huống cần kiểm thử.
Hai khách cùng thấy một sân còn trống và cùng bấm đặt: nếu ứng dụng chỉ kiểm tra lịch rồi mới lưu, cả hai yêu cầu có thể vượt qua bước kiểm tra. Vì vậy, giao diện báo còn chỗ chưa đủ; hệ thống cần một quy tắc chống trùng ngay tại cơ sở dữ liệu. Chống chồng lấn, không chỉ chống trùng giờ bắt đầu UNIQUE trên sân và giờ bắt đầu không ngăn được lịch 08:00–09:00 chồng với 08:30–09:30. PostgreSQL có kiểu khoảng thời gian và exclusion constraint để diễn đạt điều kiện không chồng lấn. Quy ước [) gồm đầu, loại cuối cho phép hai lịch 08:00–09:00 và 09:00–10:00 nối tiếp. Mẫu bảng cho ứng dụng nhiều đơn vị Ví dụ thiết kế dưới đây giữ chỗ cho trạng thái held và confirmed; cancelled không chiếm sân. Đây là mẫu minh họa, không phải migration đầy đủ cho hệ thống đang vận hành. CREATE EXTENSION IF NOT EXISTS btree_gist; CREATE TABLE court_booking ( booking_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, tenant_id bigint NOT NULL, court_id bigint NOT NULL, starts_at timestamptz NOT NULL, ends_at timestamptz NOT NULL, status text NOT NULL CHECK (status IN ('held', 'confirmed', 'cancelled')), CHECK (ends_at > starts_at), CONSTRAINT no_court_overlap EXCLUDE USING gist ( tenant_id WITH =, court_id WITH =, tstzrange(starts_at, ends_at, '[)') WITH && ) WHERE (status IN ('held', 'confirmed')) ); Vì sao có btree_gist? Extension này cung cấp phép so sánh cho các kiểu vô hướng trong GiST, giúp kết hợp tenant_id, court_id và khoảng thời gian. Hãy kiểm tra quyền và khả năng cài extension trên dịch vụ database trước khi triển khai. Những việc API vẫn phải làm Khi gặp mã SQLSTATE 23P01 (exclusion_violation), API nên trả thông báo sân vừa được người khác đặt, thay vì lỗi chung chung. Chỉ xác nhận đặt thành công sau khi transaction commit. Trong thiết kế này, giữ chỗ hết hạn cần được chuyển trạng thái bởi tác vụ xử lý riêng; thời gian trôi qua không tự đổi held thành cancelled. Danh sách kiểm thử đề xuất Thử hai yêu cầu đồng thời cho cùng sân, lịch nối tiếp, lịch chồng một phần, sân khác và tenant khác. Kiểm tra cả thao tác đổi giờ hoặc chuyển cancelled sang confirmed. Mẫu chưa xử lý thanh toán, phân quyền tenant hay quan hệ khóa ngoại; những phần đó cần thiết kế bổ sung. Nguồn tham khảo PostgreSQL 18: Range Types PostgreSQL 18: btree_gist PostgreSQL 18: CREATE TABLE PostgreSQL 18: Error Codes