Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Аномалии с данными
|
|||
|---|---|---|---|
|
#18+
Всем привет! Уже почти неделю ковыряюсь с аномалиями в транзакциях mysql, идей больше нет и решил обратиться за помощью! Server version: 5.7.20-19-log Percona Server (GPL), Release '19', Revision '3c5d3e5d53c' Transaction isolation: REPEATABLE READ БД используется на довольно нагруженном сайте, где часть задач выполняется в фоне. Используется очередь сообщений, которую обрабатывают около 10 воркеров. Каждый воркер открывает по одному соединению к БД, и как правило, оно открыто все время жизни воркера(от суток до 2х недель). Проблемы были замечены только в них. Схема данных будет сильно упрощена для наглядности. ( SQLFiddle ) Схема Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. Как видно из схемы таблица stats имеет не совсем работающий уникальный ключ, из-за того, что в нем используется nullable поле currency_id. Первая проблема которая привлекла внимание -- дубликаты записей в этой таблице вида DATE, USER_ID, CURRENCY_ID IS NULL. Первые мысли были на рейс кондишн и не использование/неправильное использование блокировок. После аудита мест создания записей рейс кондишн не был обнаружен. Наличие дубликатов в той таблице не особо портило жизнь и с этой проблемой решили пока жить. НО! немного позже стали поступать жалобы от пользователей на некорректное обновление балансов после создания "операций" (таблица operations). Опять же первым делом был сделан поиск рейс кондишинов, но и в этот раз они не были найдены. Поэтому включили general_log и стали ждать повторений багов. Вот пример запросов в котором воспроизводится баг. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. После выполнения этой транзакции, записи в таблице operations и stats были добавлены, но к моему удивлению accounts.balance содержал старое значение! Я не мог поверить своим глазам! Еще что смутило, так это то, что в таблице stats до выполнения операции уже была запись за этот день для этого пользователя currency_id is null, но почему то код вставил еще одну запись, не найдя ее по критерию поиска. Таким образом создав дубликат, о котором я писал выше. Дальше было много поисков по логам grep'ом, но особых результатов это не дало. Четко коррелируется между всеми повторениями багов вот какие факты: Аномалии всегда происходят в воркерах Аномалии всегда происходят с операциями которые добавлены в начале часа (об этом позже) Во всех логах аномалий, были выявлены также аномалии с созданием дубликата записи в таблицу stats(в случаях создания операции без багов, всегда запись находится и обновляется) Далее было принято решение посмотреть general_log на слейве, и конечно же операции UPDATE для accounts я там не увидел, но INSERT в operations и в stats там были. Полез смотреть бинлог, и в нем таже история, такое чувство что после/перед запросом Код: plsql 1. транзакция делает rollback и потом опять открывается. вот пример бинлога бинлог Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. т.е. как видим и тут UPDATE account нет. Дальше вот какие появились мысли. Так как приложение часто находится под нагрузкой, иногда возникают дедлоки, и на уровне приложения в тех местах где это возможно, оно пытается перезапустить транзакцию и повторить операцию как это советует дока к БД. Так как все аномалии встречаются близко к 00:00, начали искать процессы которые запускаются по крону, и нашли парочку тяжеловесов. Вспомнили что раньше проскакивали дедлоки в логах тоже ближе к началу каждого часа, но после того как внедрили повторение операций, они пропали.... Решил взглянуть в INNODB STATUS и увидел что последний дедлок был как раз на таблицу stats и operations. Deadlock Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. но что конкретно приводит к откату части транзакции так и не удалось понять! Собственно прошу помощи или совета, куда копать! в доке есть упоминание об откате одного SQL statement . However, if just a single SQL statement is rolled back as a result of an error, some of the locks set by the statement may be preserved. но насколько я понял по тексту, только из-за ошибки. Если там ошибка то почему драйвер ее не бросает как исключение? в общем странно все это.... Всем добра! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.02.2018, 03:13 |
|
||
|
|

start [/forum/topic.php?fid=47&msg=39599455&tid=1830072]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
38ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
42ms |
get tp. blocked users: |
2ms |
| others: | 15ms |
| total: | 144ms |

| 0 / 0 |
