Z czysto teoretycznego punktu widzenia wygląda na to, że nie blokujesz właściwych wierszy (inny warunek w pierwszej instrukcji niż w instrukcji update; poza tym blokujesz tylko jeden wiersz z powodu LIMIT 1
, podczas gdy później prawdopodobnie zaktualizujesz więcej wierszy).
Spróbuj tego:
START TRANSACTION;
SELECT v_id FROM v_ext WHERE username IS NULL AND v_id=yyy FOR UPDATE;
UPDATE v_ext SET username=xxx WHERE v_id=yyy;
COMMIT;
[edytuj]
Jeśli chodzi o przyczynę twojego impasu, to jest to prawdopodobna odpowiedź (z instrukcji ):
Bez indeksu SELECT ... FOR UPDATE
Instrukcja prawdopodobnie zablokuje całą tabelę, podczas gdy z indeksem blokuje tylko niektóre wiersze. Ponieważ nie zablokowałeś właściwych wierszy w pierwszej instrukcji, dodatkowa blokada jest uzyskiwana podczas drugiej instrukcji.
Oczywiście zakleszczenie nie może nastąpić, jeśli cała tabela jest zablokowana (tj. bez indeksu). Zakleszczenie z pewnością może wystąpić w drugiej konfiguracji.