Dlaczego po prostu tego nie spróbujemy?
Skonfiguruj bazę danych
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');
Teraz uruchom dwa połączenia z bazą danych
Połączenie 1
BEGIN;
SELECT * FROM notification WHERE `date` >= '2011-05-03' FOR UPDATE;
Połączenie 2
BEGIN;
Jeśli MySQL zablokuje wszystkie wiersze, następująca instrukcja zostanie zablokowana. Jeśli blokuje tylko zwracane wiersze, nie powinno się blokować.
SELECT * FROM notification WHERE `date` = '2011-05-02' FOR UPDATE;
I rzeczywiście to blokuje.
Co ciekawe, nie możemy również dodawać rekordów, które byłyby odczytywane, tj.
INSERT INTO notification(id, `date`, `text`) values (6, '2011-05-06', 'Notification 6');
bloki również!
W tym momencie nie mogę być pewien, czy MySQL po prostu idzie naprzód i blokuje całą tabelę, gdy pewien procent wierszy jest zablokowany, czy też naprawdę inteligentnie upewnia się, że wynik SELECT ... FOR UPDATE
zapytanie nigdy nie może być zmienione przez inną transakcję (za pomocą INSERT
, UPDATE
lub DELETE
) podczas trzymania zamka.