Cách di động duy nhất để đạt được sự nhất quán giữa các phòng và thẻ và đảm bảo rằng các phòng không bao giờ được trả lại sau khi chúng đã bị xóa là khóa chúng bằng SELECT FOR UPDATE
.
Tuy nhiên, trong một số hệ thống, khóa là một tác dụng phụ của điều khiển đồng thời và bạn đạt được kết quả tương tự mà không cần chỉ định FOR UPDATE
một cách rõ ràng.
Để giải quyết vấn đề này, Chuỗi 1 nên
SELECT id FROM rooms FOR UPDATE
, do đó ngăn Luồng 2 xóa khỏirooms
cho đến khi Chủ đề 1 được thực hiện. Có đúng không?
Điều này phụ thuộc vào điều khiển đồng thời mà hệ thống cơ sở dữ liệu của bạn đang sử dụng.
-
MyISAM
trongMySQL
(và một số hệ thống cũ khác) không khóa toàn bộ bảng trong thời gian truy vấn. -
Trong
SQL Server
,SELECT
các truy vấn đặt các ổ khóa được chia sẻ trên các bản ghi / trang / bảng mà chúng đã kiểm tra, trong khiDML
truy vấn đặt các khóa cập nhật (sau này được thăng cấp thành khóa độc quyền hoặc giảm cấp xuống khóa dùng chung). Các khóa dành riêng không tương thích với các khóa dùng chung, vì vậySELECT
hoặcDELETE
truy vấn sẽ khóa cho đến khi một phiên khác thực hiện. -
Trong cơ sở dữ liệu sử dụng
MVCC
(nhưOracle
,PostgreSQL
,MySQL
vớiInnoDB
), mộtDML
truy vấn tạo ra một bản sao của bản ghi (theo cách này hay cách khác) và nói chung người đọc không chặn người viết và ngược lại. Đối với các cơ sở dữ liệu này,SELECT FOR UPDATE
sẽ hữu ích:nó sẽ khóaSELECT
hoặcDELETE
truy vấn cho đến khi một phiên khác cam kết, giống nhưSQL Server
không.
Khi nào thì nên sử dụng
REPEATABLE_READ
cách ly giao dịch so vớiREAD_COMMITTED
vớiSELECT ... FOR UPDATE
?
Nói chung, REPEATABLE READ
không cấm các hàng ảo (các hàng đã xuất hiện hoặc biến mất trong một giao dịch khác, thay vì được sửa đổi)
-
Trong
Oracle
vàPostgreSQL
cũ hơn phiên bản,REPEATABLE READ
thực sự là một từ đồng nghĩa vớiSERIALIZABLE
. Về cơ bản, điều này có nghĩa là giao dịch không thấy các thay đổi được thực hiện sau khi nó đã bắt đầu. Vì vậy, trong thiết lập này,Thread 1
cuối cùng truy vấn sẽ trả về căn phòng như thể nó chưa bao giờ bị xóa (có thể có hoặc không như những gì bạn muốn). Nếu bạn không muốn hiển thị các phòng sau khi chúng đã bị xóa, bạn nên khóa các hàng bằngSELECT FOR UPDATE
-
Trong
InnoDB
,REPEATABLE READ
vàSERIALIZABLE
là những thứ khác nhau:người đọc trongSERIALIZABLE
chế độ đặt khóa phím tiếp theo trên các bản ghi mà chúng đánh giá, ngăn chặn hiệu quảDML
đồng thời về họ. Vì vậy, bạn không cầnSELECT FOR UPDATE
ở chế độ có thể tuần tự hóa, nhưng cần chúng trongREPEATABLE READ
hoặcREAD COMMITED
.
Lưu ý rằng tiêu chuẩn về các chế độ cách ly quy định rằng bạn không thấy một số câu hỏi nhất định trong các truy vấn của mình nhưng không xác định cách thức (với khóa hoặc với MVCC
hoặc cách khác).
Khi tôi nói "bạn không cần SELECT FOR UPDATE
"Tôi thực sự nên thêm" vì tác dụng phụ của việc triển khai công cụ cơ sở dữ liệu nhất định ".