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”.