Có một vài tình huống có thể dễ giải quyết và một tình huống nguy hiểm không xảy ra.
Đối với người dùng nhập một giá trị, sau đó nhập cùng một giá trị sau đó một CHỌN đơn giản trước khi INSERT sẽ phát hiện vấn đề. Điều này hoạt động trong trường hợp một người dùng gửi một giá trị và một thời gian sau, một người dùng khác gửi cùng một giá trị.
Nếu người dùng gửi danh sách các giá trị có trùng lặp - giả sử {ABC, DEF, ABC} - trong một lần gọi mã, ứng dụng có thể phát hiện và lọc các bản sao, có thể gây ra lỗi. Bạn cũng cần kiểm tra DB không chứa bất kỳ giá trị duy nhất nào trước khi chèn.
Kịch bản khó khăn là khi một người viết viết bên trong DBMS cùng lúc với người viết khác và họ đang viết cùng một giá trị. Sau đó, bạn có một cuộc đua một điều kiện giữa họ. Vì DBMS (rất có thể - bạn không nói bạn đang sử dụng hệ thống nào), một hệ thống đa nhiệm được ưu tiên, bất kỳ nhiệm vụ nào cũng có thể bị tạm dừng tại bất kỳ thời điểm nào trong quá trình thực thi. Điều đó có nghĩa là tác vụ của user1 có thể kiểm tra không có hàng nào hiện có, sau đó tác vụ của user2 có thể kiểm tra không có hàng nào tồn tại, sau đó tác vụ của user1 có thể chèn hàng đó, sau đó tác vụ của user2 có thể chèn hàng đó. Tại mỗi thời điểm, các nhiệm vụ đều hạnh phúc riêng lẻ, họ đang làm điều đúng đắn. Trên toàn cầu, một lỗi xảy ra.
Thông thường, một DBMS sẽ xử lý việc này bằng cách khóa một giá trị trong câu hỏi. Trong vấn đề này, bạn đang tạo một hàng mới để không có gì để khóa. Câu trả lời là một khóa phạm vi. Vì nó cho thấy điều này khóa một loạt các giá trị, cho dù chúng có tồn tại hay không. Khi khóa, phạm vi đó không thể được truy cập bởi một tác vụ khác cho đến khi khóa được giải phóng. Để có được khóa phạm vi, bạn phải chỉ định và mức cô lập SERIALIZABLE . Hiện tượng một nhiệm vụ khác lẻn vào một hàng sau khi nhiệm vụ của bạn đã được kiểm tra được gọi là các bản ghi ảo .
Đặt mức cô lập thành Nối tiếp trên toàn bộ ứng dụng sẽ có ý nghĩa. Thông lượng sẽ được giảm. Các điều kiện chủng tộc khác hoạt động đủ tốt trong quá khứ có thể bắt đầu hiển thị lỗi ngay bây giờ. Tôi sẽ đề nghị thiết lập nó trên kết nối thực thi mã tạo ra trùng lặp của bạn và để lại phần còn lại của ứng dụng.
Một thay thế dựa trên mã là để kiểm tra sau khi viết chứ không phải trước đó. Vì vậy, thực hiện INSERT, sau đó đếm số lượng hàng có giá trị băm đó. Nếu có trùng lặp rollback hành động. Điều này có thể có một số kết quả đồi trụy. Nói tác vụ 1 viết rồi tác vụ 2. Sau đó, nhiệm vụ 1 kiểm tra và tìm một bản sao. Nó quay trở lại mặc dù là lần đầu tiên. Tương tự, cả hai tác vụ có thể phát hiện trùng lặp và cả rollback. Nhưng ít nhất bạn sẽ có một thông điệp để làm việc, một cơ chế thử lại và không có bản sao mới. Rollback được nhăn mặt, giống như sử dụng các ngoại lệ để kiểm soát dòng chương trình. Lưu ý rằng tất cảcông việc trong giao dịch sẽ được khôi phục, không chỉ là việc viết trùng lặp. Và bạn sẽ phải có các giao dịch rõ ràng có thể làm giảm sự tương tranh. Kiểm tra trùng lặp sẽ chậm khủng khiếp trừ khi bạn có một chỉ mục trên hàm băm. Nếu bạn làm bạn cũng có thể làm cho nó một duy nhất!
Như bạn đã nhận xét, giải pháp thực sự là một chỉ số duy nhất. Dường như với tôi như thế này sẽ phù hợp với cửa sổ bảo trì của bạn (mặc dù tất nhiên bạn biết rõ hệ thống của mình nhất). Nói băm là tám byte. Đối với một trăm triệu hàng khoảng 1GB. Kinh nghiệm cho thấy một chút phần cứng hợp lý sẽ xử lý nhiều hàng này trong một hoặc hai phút. Kiểm tra và loại bỏ trùng lặp sẽ thêm vào điều này, nhưng có thể được viết kịch bản trước. Đây chỉ là một bên, mặc dù.