Това е правилното. Редовете в таблицата, от която се чете, са заключени със споделено заключване (SELECT е имплицитно LOCK IN SHARE MODE ). Няма начин да се избегне това. Това е нещо като това, за което питате системата:копирайте всички редове, които отговарят на условие. Единственият начин да се гарантира, че всъщност всички редове отговарят на условието и че този списък не се променя по време или непосредствено след изпълнението на този израз, е да заключите редовете.
Като пояснение защо не можете да INSERT с group_id = 2 :
Това е свързано с това, че вашата заявка е конкретно WHERE group_id = 3 AND created < '2014-01-04' на KEY group_id_created (group_id, created) . За да търсите всички редове, които съответстват на group_id = 3 AND created < '2014-01-04' индексът ще бъде обходен назад, като се започне с първия ред, който надвишава горната граница на това условие, която е (3, '2014-01-14') и продължава до намиране на ред, който не съответства на условието, което след created няма долна граница, ще бъде първият ред, където group_id < 3 което разбира се е group_id = 2 .
Това означава, че първият ред се среща с group_id = 2 есъщо заключено, което ще бъде редът с максималния created стойност. Това ще направи невъзможно INSERT в "пропастта" между (2, MAX(created)) и (3, MIN(created)) (разбира се, не подходящ SQL, а просто псевдо-SQL), въпреки че това не е конкретно „заключване на празнина“.