Tại sao chúng ta không thử nó?
Thiết lập cơ sở dữ liệu
CREATE DATABASE so1;
USE so1;
CREATE TABLE notification (`id` BIGINT(20), `date` DATE, `text` TEXT) ENGINE=InnoDB;
INSERT INTO notification(id, `date`, `text`) values (1, '2011-05-01', 'Notification 1');
INSERT INTO notification(id, `date`, `text`) values (2, '2011-05-02', 'Notification 2');
INSERT INTO notification(id, `date`, `text`) values (3, '2011-05-03', 'Notification 3');
INSERT INTO notification(id, `date`, `text`) values (4, '2011-05-04', 'Notification 4');
INSERT INTO notification(id, `date`, `text`) values (5, '2011-05-05', 'Notification 5');
Bây giờ, hãy bắt đầu hai kết nối cơ sở dữ liệu
Kết nối 1
BEGIN;
SELECT * FROM notification WHERE `date` >= '2011-05-03' FOR UPDATE;
Kết nối 2
BEGIN;
Nếu MySQL khóa tất cả các hàng, câu lệnh sau sẽ chặn. Nếu nó chỉ khóa các hàng mà nó trả về, nó sẽ không chặn.
SELECT * FROM notification WHERE `date` = '2011-05-02' FOR UPDATE;
Và thực sự thì nó chặn.
Điều thú vị là chúng tôi cũng không thể thêm các bản ghi sẽ được đọc, tức là
INSERT INTO notification(id, `date`, `text`) values (6, '2011-05-06', 'Notification 6');
cả khối nữa!
Tại thời điểm này, tôi không thể chắc chắn liệu MySQL chỉ tiếp tục và khóa toàn bộ bảng khi một tỷ lệ phần trăm hàng nhất định bị khóa hay nơi mà nó thực sự thông minh trong việc đảm bảo kết quả của SELECT ... FOR UPDATE
không bao giờ có thể thay đổi truy vấn bởi một giao dịch khác (với INSERT
, UPDATE
hoặc DELETE
) trong khi khóa đang được giữ.