Как алгоритмически СУБД определяет, что два потока вошли в взаимный дедлок?

Может кто знает,
уже эта тема актуальна для реализации

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
СУБД
разные бывают

Вроде реализовал разруливание дедлоков.
Общий алгоритм такой как писали ниже. Если блокировка длится больше 10 сек, алгоритм начинает разбирательства и проверки на счет дедлоков. Для этого проходится единожды по списку транзакций и проверяет нет ли взаимной блокировки. Если есть, то та транзакция которая обратилась первой к ядру системы с жалобой и подозрением на дедлок и прибивается (как жесток мир =)).

Что интересно, в отличии от других баз, которые очень мало дают инфы какие запросы, по каким данным вошли в дедлок, эта база будет выдавать очень подробный лог по дедлоку, со всей инфой. Какие два запроса вызвали дедлок, какие данные были заблокированы обоюдно.

Есть несколько методов, которые комбинируются по обстановке, например:
1. Просто таймаут. В общем-то не только ради клинчей (deadlocks), но и ради любых других проблем (диск сбоит...)
2. Поиск по графу связей. Например, если задача X залочила A, потом B, строится граф с ориентированным ребром A->B; если Y залочила B, потом A, строится аналогично B->A. Видя цикл между A->B и B->A (сразу по попытке Y залочить A, или чуть погодя), обнаруживается факт взаимной блокировки.

Да, тут уже пришли кое какие мысли.
Сначала сделать таймаут, если таймаут прошли проверить на дедлок.
А проверить придумал так. Каждая транзакция помечается какой именно транзакцией она заблочена. Когда пришло время разбирательства, пробегаем по списку и смотрим кто ссылается друг на друга взаимно.

Да, можно и через связи транзакций.

идея с графами хороша, но как У может локнуть А если А уже локнута ? лок для того и делается что бы никто не мешал. можна сделать шеринг лок (слок) но тогда вторая транзакция может только читать данные и локать не может.

но как У может локнуть А если А уже локнута ?

Я сократил из описания важные моменты, да. Описанный сценарий возможен, если по времени работа транзакций идёт параллельно с тем, что они происходят в порядке: X лочит A; Y лочит B; X заказывает лок B и становится в ожидание; Y заказывает лок A и становится в ожидание. Иначе (если бы X взяла и A, и B до того, как пришла A) было бы ожидание Y’ом снятия лока X’ом, но не взаимная блокировка. Коллега бубен-ком уже это понимал, поэтому я не стал углубляться.

можна сделать шеринг лок (слок)

Есть ещё ситуация апгрейда shared lock до exclusive lock атомарно, не имея момента, когда shared снято — в БД это как раз часто, когда переходит от «прочитал данные, проверил на соответствие задаче» к «иду их модифицировать». Там точно так же можно стать на ожидание.

Обычно дедлоков стараются избегать, для этого транзакции проверяются на serializable путем построения precedence graph и поиска в нем лупов, если лупы найдены то транзакции ну сериалайзабл и будут разнесены во времени. таким образом избегаются дедлоки в параллельных транзакциях. Второй способ избегания локов- ту фейс лок протокол, стрикт ту фейс лок и три фейс лок. Ищите на ютьюбе или в интете concurrency control. Вообщем дешевле избегать чем получать дедлоки.

Как избегать это немножко другая история. Тут нужно решения «из нутри» базы данных. Вот пришел момент когда два потока заблочили друг друга. Как быстро и надежно определить, что они лочат друг друга, плюс забросить в лог какие именно запросы и по каким данным привели к взаимному дедлоку...

таймаут на локах проверять, если лок длится дольше какого то времени то считается что транзакция попала в дедлок и ей нада ролбек

Підписатись на коментарі