Trước hết, việc khóa bảng sẽ không ngăn phiên khác phát hành SELECT
tuyên bố chống lại dữ liệu.
Trong Phiên 1, nếu tôi khóa bảng
SQL> lock table foo in exclusive mode;
Table(s) Locked.
Sau đó, tôi có thể bắt đầu Phiên 2 và truy vấn dữ liệu tất cả những gì tôi muốn
SQL> select * from foo;
COL1
----------
1
1
Trong Oracle, người viết không chặn trình đọc nên bạn không bao giờ có thể ngăn một phiên khác truy vấn dữ liệu trong bảng.
Có vẻ như những gì bạn đang cố gắng thực hiện là khóa bi quan. Trong trường hợp đó, thay vì khóa bảng, bạn thực hiện SELECT FOR UPDATE
khóa mục nhập cụ thể mà bạn định xử lý. Miễn là tất cả các phiên khác cũng cố gắng thực hiện SELECT FOR UPDATE
(tùy thuộc vào phiên bản Oracle, có thể thêm SKIP LOCKED
bộ định tính và / hoặc WAIT
vòng loại). Điều đó khóa hàng cụ thể mà bạn đang xử lý và cho phép phiên thứ hai chọn một hàng khác hoặc hết thời gian hoặc nhận thấy không có hàng nào để xử lý tùy thuộc vào chi tiết cụ thể của việc triển khai. Điều đó không liên quan đến việc khóa bảng.
Cách duy nhất để khóa được phát hành là đối với phiên có được nó để giải phóng nó (thường bằng cách kết thúc giao dịch) hoặc đối với phiên đã mua nó bị chấm dứt. Nếu ứng dụng khách vẫn đang chạy nhưng không làm bất cứ điều gì để giải phóng khóa hoặc kết thúc phiên, khóa sẽ được giữ vô thời hạn. Một DBA sẽ cần phải hủy phiên một cách rõ ràng, để giao dịch quay trở lại và giải phóng khóa để hệ thống hoạt động trở lại. Nếu ứng dụng khách ngừng chạy hoặc ít nhất là ngừng phản hồi (tôi vẫn chưa rõ chính xác bạn đang thảo luận về trường hợp lỗi nào), có thể bật tính năng phát hiện kết nối chết (DCD) thông qua tham số 'SQLNET.EXPIRE_TIME' ở cấp cơ sở dữ liệu sẽ khiến cơ sở dữ liệu xác định rằng máy khách không đáp ứng và tự động hủy phiên, khôi phục giao dịch và giải phóng khóa.
Tuy nhiên, nếu có nhiều phiên xử lý dữ liệu, thì thường tốt hơn là sử dụng một số hình thức khóa lạc quan. Nếu không, bạn đang thiết kế một hệ thống chắc chắn sẽ cần DBA khẩn trương tìm và giết các phiên để khiến người dùng doanh nghiệp hoạt động trở lại và điều đó sẽ đòi hỏi sự can thiệp ngày càng nhiều hơn khi nó nhận được nhiều hơn. Đó không phải là điều mà các DBA thích làm và không phải là điều mà người dùng doanh nghiệp thích phàn nàn. Một sơ đồ khóa lạc quan đơn giản sẽ giống như
- Chọn một khóa để xử lý và một số loại ngày cho biết lần cuối cùng hàng được cập nhật.
- Cập nhật cột trạng thái thành "đang xử lý" để các phiên khác không cố gắng xử lý cùng hàng đó.
- Xử lý mục nhập trong đơn đăng ký của bạn
- Khi bạn xử lý xong, hãy cập nhật dữ liệu bằng khóa và thời gian bạn đã chọn ở bước đầu tiên. Nếu bạn cập nhật 1 hàng, bạn biết rằng không có phiên nào khác đã sửa đổi dữ liệu được đề cập kể từ khi bạn chọn nó. Nếu bạn cập nhật 0 hàng, bạn biết rằng một số phiên khác đã sửa đổi dữ liệu kể từ khi bạn chọn nó.
Với kiểu kiến trúc này, việc truy vấn cơ sở dữ liệu tương đối dễ dàng để xem những hàng nào đang được xử lý và ví dụ:có một công việc đặt cột trạng thái trở lại "chưa xử lý" sau một khoảng thời gian nếu máy khách không hoàn thành. Các phiên khác thực sự dễ dàng chọn một hàng khác để xử lý. Và nó tương đối an toàn nếu ví dụ:ứng dụng bị đóng băng trong vài giờ và sau đó phục hồi vì nó chỉ phát hiện ra sau khi xử lý xong mà một số phiên khác đã xử lý lại hàng.