Един лесен трик, който може да помогне при повечето блокирания, е сортирането на операциите в определен ред.
Получавате блокиране, когато две транзакции се опитват да заключат две заключвания при противоположни поръчки, т.е.:
- връзка 1:ключ за заключване (1), ключ за заключване (2);
- връзка 2:ключ за заключване (2), ключ за заключване (1);
Ако и двете се изпълняват едновременно, връзка 1 ще заключи ключ (1), връзка 2 ще заключи ключ (2) и всяка връзка ще изчака другата да освободи ключа -> застой.
Сега, ако промените заявките си така, че връзките да заключват ключовете в същия ред, т.е.:
- връзка 1:ключ за заключване (1), ключ за заключване (2);
- връзка 2:ключ за заключване (1 ), ключ за заключване (2 );
ще бъде невъзможно да се стигне до безизходица.
Ето какво предлагам:
-
Уверете се, че нямате други заявки, които да заключват достъпа до повече от един ключ наведнъж, освен оператора delete. ако го направите (а подозирам, че го правите), подредете техните WHERE в (k1,k2,..kn) във възходящ ред.
-
Коригирайте оператора за изтриване да работи във възходящ ред:
Промяна
DELETE FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
До
DELETE FROM onlineusers
WHERE id IN (
SELECT id FROM onlineusers
WHERE datetime <= now() - INTERVAL 900 SECOND
ORDER BY id
) u;
Друго нещо, което трябва да имате предвид, е, че MySQL документацията предполага, че в случай на застой клиентът трябва да опита отново автоматично. можете да добавите тази логика към вашия клиентски код. (Да речем, 3 опита за тази конкретна грешка, преди да се откажете).