Está correto. As linhas na tabela que estão sendo lidas são bloqueadas com um bloqueio compartilhado (o
SELECT é implicitamente LOCK IN SHARE MODE ). Não há como evitar isso. É mais ou menos o que você está pedindo ao sistema:copie todas as linhas que correspondem a uma condição. A única maneira de garantir que todas as linhas correspondam à condição e que essa lista não seja alterada durante ou imediatamente após a execução dessa instrução é bloquear as linhas. Como um esclarecimento sobre por que você não consegue
INSERT com group_id = 2 :Isso tem a ver com sua consulta sendo especificamente
WHERE group_id = 3 AND created < '2014-01-04' em KEY group_id_created (group_id, created) . Para pesquisar todas as linhas que correspondem a group_id = 3 AND created < '2014-01-04' o índice será percorrido para trás começando com a primeira linha que excede essa condição do limite superior, que é (3, '2014-01-14') e continuando até encontrar uma linha que não corresponda à condição, que desde created não tem limite inferior será a primeira linha onde group_id < 3 que, claro, é group_id = 2 . Isso significa que a primeira linha encontrada com
group_id = 2 é também bloqueado, que será a linha com o máximo de created valor. Isso tornará impossível INSERT no "intervalo" entre (2, MAX(created)) e (3, MIN(created)) (não é SQL adequado, é claro, apenas pseudo-SQL), embora isso não seja um "bloqueio de lacuna" especificamente.