To je správně. Řádky v tabulce, ze které se čte, jsou uzamčeny sdíleným zámkem (SELECT je implicitně LOCK IN SHARE MODE ). Neexistuje způsob, jak se tomu vyhnout. Je to něco, o co systém žádáte:zkopírujte všechny řádky, které odpovídají podmínce. Jediným způsobem, jak zajistit, že všechny řádky, které splňují podmínku a že se tento seznam nezmění během nebo bezprostředně po provedení daného příkazu, je uzamknout řádky.
Jako vysvětlení ohledně toho, proč nemůžete INSERT s group_id = 2 :
Souvisí to s tím, že váš dotaz je konkrétně WHERE group_id = 3 AND created < '2014-01-04' na KEY group_id_created (group_id, created) . Chcete-li vyhledat všechny řádky, které odpovídají group_id = 3 AND created < '2014-01-04' index bude procházet pozpátku počínaje prvním řádkem, který přesahuje tuto podmínku, horní mez, což je (3, '2014-01-14') a pokračujte, dokud nenajdete řádek, který neodpovídá podmínce, která byla od té doby created nemá dolní hranici bude první řádek, kde group_id < 3 což je samozřejmě group_id = 2 .
To znamená, že na prvním řádku bylo zjištěno group_id = 2 je také locked, což bude řádek s maximálním created hodnota. To znemožní INSERT do "mezery" mezi (2, MAX(created)) a (3, MIN(created)) (samozřejmě ne správné SQL, jen pseudo-SQL), i když se nejedná konkrétně o "zámek mezery".