To jest poprawne. Wiersze w tabeli, z której są odczytywane, są zablokowane wspólną blokadą (SELECT
jest domyślnie LOCK IN SHARE MODE
). Nie ma sposobu, aby tego uniknąć. Jest to rodzaj tego, o co prosisz system:skopiuj wszystkie wiersze, które pasują do warunku. Jedynym sposobem, aby upewnić się, że w rzeczywistości wszystkie wiersze spełniają warunek i że lista nie zmieni się w trakcie lub bezpośrednio po wykonaniu tej instrukcji, jest zablokowanie wierszy.
Jako wyjaśnienie, dlaczego nie możesz INSERT
z group_id = 2
:
Ma to związek z tym, że zapytanie jest konkretnie WHERE group_id = 3 AND created < '2014-01-04'
na KEY group_id_created (group_id, created)
. Aby przeszukać wszystkie wiersze pasujące do group_id = 3 AND created < '2014-01-04'
indeks zostanie przesunięty wstecz, zaczynając od pierwszego wiersza, który przekracza ten warunek, górną granicę, którą jest (3, '2014-01-14')
i kontynuuj aż do znalezienia wiersza, który nie pasuje do warunku, który od created
nie ma dolnej granicy, będzie pierwszym wierszem, w którym group_id < 3
co oczywiście to group_id = 2
.
Oznacza to, że pierwszy napotkany wiersz z group_id = 2
jest również zablokowany, który będzie wierszem z maksymalnym created
wartość. Uniemożliwi to INSERT
w "lukę" między (2, MAX(created))
i (3, MIN(created))
(oczywiście nie jest to właściwy SQL, tylko pseudo-SQL), chociaż nie jest to konkretnie „blokada luk”.