SELECT FOR UPDATE
obtém um bloqueio exclusivo de intenção na tabela antes de obter o bloqueio exclusivo no registro. Portanto, neste cenário:
X1: SELECT FOR UPDATE -- holds IX, holds X on 'lock_name'
X2: SELECT FOR UPDATE -- holds IX, waits for X on 'lock_name'
X1: INSERT -- holds IX, waits for X for the gap on `id`
ocorre um deadlock, pois ambas as transações estão mantendo um
IX
trava na mesa e esperando por um X
bloqueio nos registros. Na verdade, esse mesmo cenário é descrito no
MySQL
manual de travamento
. Para contornar isso, você precisa se livrar de todos os índices, exceto aquele em que você está pesquisando, que é
lock_name
. Basta soltar a chave primária em
id
.