имеется куча потоков, которая вызывает одну и туже хранимку, которая там что-то сложное делает с базой.
вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
вопрос 3: как наилучшим образом бороться, чтобы не растерять алюсы многопоточности? у меня два выхода: 1- блокировать mutex'om момент вызова процедуры; 2-ловить вот это
Transaction (Process ID 140) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
и делать то что говорится, то бишь Rerun the transaction
18.05.06 17:51: Перенесено модератором из '.NET' — AndrewVK
Здравствуйте, lumf, Вы писали:
L>тема достаточно избитая, но все же...
L>имеется куча потоков, которая вызывает одну и туже хранимку, которая там что-то сложное делает с базой.
L>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
L>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
L>вопрос 3: как наилучшим образом бороться, чтобы не растерять алюсы многопоточности? у меня два выхода: 1- блокировать mutex'om момент вызова процедуры; 2-ловить вот это
В форум БД, пользоваться поиском, искать статью на RSDN по взаимоблокировкам
Здравствуйте, lumf, Вы писали:
L>тема достаточно избитая, но все же...
L>имеется куча потоков, которая вызывает одну и туже хранимку, которая там что-то сложное делает с базой.
L>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
L>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
L>вопрос 3: как наилучшим образом бороться, чтобы не растерять алюсы многопоточности? у меня два выхода: 1- блокировать mutex'om момент вызова процедуры; 2-ловить вот это
L>
L>Transaction (Process ID 140) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
L>
L>и делать то что говорится, то бишь Rerun the transaction
Mutex не поможет если будет запущено несколько приложений, мы устанавливали режим блокировки строки вместо блокировки страницы это уменьшило вероятность deadlocks, а в остальном — в приложении обрабатывали ситуацию и повторяли запрос, вроде работало.
Здравствуйте, DemAS, Вы писали:
DAS>Здравствуйте, lumf, Вы писали:
L>>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
DAS> нет
L>>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
DAS> нет
Здравствуйте, SergPas, Вы писали:
SP>Здравствуйте, DemAS, Вы писали:
DAS>>Здравствуйте, lumf, Вы писали:
L>>>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
DAS>> нет
L>>>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
DAS>> нет
SP>IMXO — все с точностью наоборот.
Здравствуйте, DemAS, Вы писали: L>>>>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
DAS>>> нет
L>>>>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
DAS>>> нет
SP>>IMXO — все с точностью наоборот.
DAS> Опиши, как ты это видишь?
dedlock — это не проблема (нормальная ситуация MSSQL-сервера), тем более не проблема приложения.
Не важно сколько DML-запросов выполняется, если изменяемые данные(ключи, индексы ...)
приходятся на заблокированную страницу (обычно 4K) возникает блокировка — это нормально,
проще провторить запрос и не беспокоиться. Можно бороться другими способами, но IMXO это
только усложнит задачу и снизит производительность.
SP>dedlock — это не проблема (нормальная ситуация MSSQL-сервера)
Блокировка — это не проблема. Deadlock — повод задуматься и сделать так, чтобы не было.
Блокировка, это когда 2 конкурирующих процесса борются за одни ресурсы и при этом процесс 1 ожидает пока процесс 2 освободит ресурс, а 2-ой процесс ожидает 1-ый.
Допустим у нас есть два ресурса А и Б, и два процесса 1 и 2.
1) Процесс 1 блокирует ресурс А
2) Процесс 2 блокирует ресурс Б
3) Процесс 1 хочет заблокировать ресурс Б, но не может и ожидает процесс 2
4) Процесс 2 хочет заблокировать ресурс А, но не может и ожидает процесс 1
Классическая взаимоблокировка.
Как вообще может возникнуть deadlock при работе с одним (и только одним) ресурсом ?
Прошу прощения, читать конечно надо так:
DAS> ВзаимоБлокировка, это когда 2 конкурирующих процесса борются за одни ресурсы и при этом процесс 1 ожидает пока процесс 2 освободит ресурс, а 2-ой процесс ожидает 1-ый.
Здравствуйте, DemAS, Вы писали:
DAS>Здравствуйте, SergPas, Вы писали:
DAS> Допустим у нас есть два ресурса А и Б, и два процесса 1 и 2. DAS> 1) Процесс 1 блокирует ресурс А DAS> 2) Процесс 2 блокирует ресурс Б DAS> 3) Процесс 1 хочет заблокировать ресурс Б, но не может и ожидает процесс 2 DAS> 4) Процесс 2 хочет заблокировать ресурс А, но не может и ожидает процесс 1
DAS> Классическая взаимоблокировка.
DAS> Как вообще может возникнуть deadlock при работе с одним (и только одним) ресурсом ?
Со всем согласен, блокировка возможна — взаимоблокировка нет.
Но в конкретном случае сложно заранее определить из-за какого ресурса возникает "проблема".
У MSSQL при возникновении блокировки (не deadlock) запрос становиться в ожидание в специальную
очередь (размер которой настраивается параметрами сервера), при переполнении очереди происходит эскалация
блокировки со строки до страницы и так до таблицы в целом. После чего вероятность deadlock возрастает.
При возникновении deadlock MSSQL выдергивает запрос из очереди и сообщает об этом приложению и так до тех пор пока
не разрулится ситуация.
Давно это было, я уже всех тонкостей не помню, перешли на Oracle там таких проблем нет.
А за подробностями лучше обратиться на www.sql.ru — там все гораздо подробнее.
Здравствуйте, SergPas, Вы писали:
SP>Со всем согласен, блокировка возможна — взаимоблокировка нет.
Ага. А в исходном сообщении, человек как раз и спрашивал про взаимоблокировку, поэтому я и ответил "нет".
SP>У MSSQL при возникновении блокировки (не deadlock) запрос становиться в ожидание в специальную SP>очередь (размер которой настраивается параметрами сервера), при переполнении очереди происходит эскалация SP>блокировки со строки до страницы и так до таблицы в целом.
Насколько я помню, тут нет никакой очереди. Если менеджеру блокировки для хранения информации о наложенных блокировках требуется более 40% памяти, то он пытается эскалировать блокировки. В случае, если другие строки таблицы заблокированы другим процессом — эскалация не происходит.
SP>После чего вероятность deadlock возрастает.
Да за счет чего она увеличивается то? Мы по прежнему имеем один ресурс — на этот раз таблицу, за которую происходит борьба. Откуда возьмется deadlock ?
SP>При возникновении deadlock MSSQL выдергивает запрос из очереди и сообщает об этом приложению и так до тех пор пока SP>не разрулится ситуация.
При возникновении deadlock сервер стоит граф блокировок и выбирает один из процессов, как кандидат на rollback. После чего второй процесс продолжает свое выполнение.
SP>Давно это было, я уже всех тонкостей не помню, перешли на Oracle там таких проблем нет.
Здравствуйте, DemAS, Вы писали:
DAS> Насколько я помню, тут нет никакой очереди. Если менеджеру блокировки для хранения информации о наложенных блокировках требуется более 40% памяти, то он пытается эскалировать блокировки. В случае, если другие строки таблицы заблокированы другим процессом — эскалация не происходит.
Я имел дело с MSSQL6.5 не знал что все изменилось.
SP>>После чего вероятность deadlock возрастает.
DAS> Да за счет чего она увеличивается то? Мы по прежнему имеем один ресурс — на этот раз таблицу, за которую происходит борьба. Откуда возьмется deadlock ?
Дык, с этой таблицей (другими записями) можер работать кто угодно другой.
SP>>Давно это было, я уже всех тонкостей не помню, перешли на Oracle там таких проблем нет.
DAS> Там есть другие проблемы
Это точно, особенно для разработки клиентских приложений.
Здравствуйте, BlackTigerAP, Вы писали:
BTA>Блокировать надо таблицы. Притом в правильном порядке, едином для всех операций. Тогда dead-lock-ов не будет (почти).
Ну что-ж... И тебе рекомендую почитать статейку по взимоблокировкам.
BTA>Когда пишешь многопользовотельское приложение, нужно ОЧЕНЬ хорошо планировать. Когда многопоточное — планировать ЕЩЕ больше.
BTA>На коленке многопользовательские приложения не собираются и "по книжке" не пишутся.
Вроде трудно не согласиться, но после "блокировать таблицы" как-то выглядит не очень.
Здравствуйте, BlackTigerAP, Вы писали:
DemAS>>> Прям так сразу всю таблицу? Да еще и в многопользовательском приложении?
BTA>Не надо меня прямо так буквально понимать. Ну не всю таблицу, а необходимый кусок. Хотя иногда надо бы и всю таблицу. Зависит от характера изменений.
Не понимаешь ты механизм блокировок MS SQL, а советы даешь. Сколько пишу на MS SQL, ну вот НИ РАЗУ не потребовалось ставить хинт tablock или tablockx. Уровень изоляции транзакций до serializable в нескольких (менее 5) запросах — есть хинты. Вот таким образом и надо работать с блокировками.
SP>dedlock — это не проблема (нормальная ситуация MSSQL-сервера), тем более не проблема приложения.
Что-то путаешь: блокировку и взимоблокировку.
SP>Не важно сколько DML-запросов выполняется, если изменяемые данные(ключи, индексы ...) SP>приходятся на заблокированную страницу (обычно 4K) возникает блокировка — это нормально,
Ну вобще-то 8К
SP>проще провторить запрос и не беспокоиться. Можно бороться другими способами, но IMXO это SP>только усложнит задачу и снизит производительность.
2all: Еще раз: читать статью, а потом с умным видом давать советы
Здравствуйте, SergPas, Вы писали:
SP>Здравствуйте, DemAS, Вы писали:
DAS>> Насколько я помню, тут нет никакой очереди. Если менеджеру блокировки для хранения информации о наложенных блокировках требуется более 40% памяти, то он пытается эскалировать блокировки. В случае, если другие строки таблицы заблокированы другим процессом — эскалация не происходит.
SP>Я имел дело с MSSQL6.5 не знал что все изменилось.
Открою секрет: Windows XP все-таки отличается от Windows 3.1. Впрочем как и MS SQL 2005 отличается от MS SQL 6.5
Здравствуйте, _d_m_, Вы писали:
___>Уровень изоляции транзакций до serializable в нескольких (менее 5) запросах — есть хинты. Вот таким образом и надо работать с блокировками.
И при этом все стоят и нервно курят, пока один человек выполнит свой запрос? А если они только почитать чего-нить хотят, причем совсем не из тех таблиц, которые изменяет работающая в данный момент транзакция?
Здравствуйте, hugo, Вы писали:
H>Здравствуйте, _d_m_, Вы писали:
___>>Уровень изоляции транзакций до serializable в нескольких (менее 5) запросах — есть хинты. Вот таким образом и надо работать с блокировками.
H>И при этом все стоят и нервно курят, пока один человек выполнит свой запрос? А если они только почитать чего-нить хотят, причем совсем не из тех таблиц, которые изменяет работающая в данный момент транзакция?
RTFM уважаемый, RTFM.
Во первых. Уточняю: <5 запросов на все приложение — а оно не маленькое. Там где это действительно необходимо.
Во вторых. Я бы сказал выполнит: связку запрос+(апдейт|вставка|удаление). Иначе, а зачем тогда serizlizable?
Во третьих. Они и затянуться не успеют.
В четвертых. Вопрос курения встанет, только если им потребуются имено в заблокированный диапазон данных (зачастую много меньше таблицы):
— писать до момента комита блокирующей транзакции;
— читать после изменения данных блокирующей транзакцией и до ее комита.
Заметь: как слово "диапазон" отличается от "вся таблица".
В пятых. Что им может помешать читать из любых других таблиц?
Здравствуйте, BlackTigerAP, Вы писали:
DemAS>>> Как вообще может возникнуть deadlock при работе с одним (и только одним) ресурсом ?
BTA>Лёгко!!! Достаточно вспомнить, что для SQLServer является "блокируемым ресурсом". Для танкистов — запись.
Ок. А теперь приведи пример работы, когда два процесса работая с одной записью взаимноблокируют друг друга.
BTA>Они же (процессы) не с одной записью работают.
Посмотри изначальный вопрос:
вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
... << RSDN@Home 1.2.0 alpha rev. 643>>
Re[3]: многопоточность и deadlock в mssql2000
От:
Аноним
Дата:
05.05.06 11:07
Оценка:
2 _d_m_:
Ага, по таким вот "сериализаторавщикам" даже на Channel9 прошлись люди из МС. После таких деятелей и рождаются мифы о нежизнеспособности приложений на SQLServer, и заказчики плюются и проклинают тот день и час, когда связались с SQLServer и уходят на Oracle.
Здравствуйте, BlackTigerAP, Вы писали:
BTA>2 _d_m_:
BTA>Ага, по таким вот "сериализаторавщикам" даже на Channel9 прошлись люди из МС. После таких деятелей и рождаются мифы о нежизнеспособности приложений на SQLServer, и заказчики плюются и проклинают тот день и час, когда связались с SQLServer и уходят на Oracle.
По каким таким? Что ты вообще обо мне знаешь?
Нет, наоборот. Мифы о нежизнеспособности SQLServer рождаются, когда некомпетентные в этих вопросах люди советуют блокировать таблицами. Мои клиенты себя чуствуют комфортно в том числе благодаря грамотно поставленным уровням изоляции. 99.9% запросов курят read commited и лишь уровень некоторых единичных запросов, там где это действительно необходимо — повышен до serializable.
L>вопрос 1: если бы в хранимке была лишь одна инструкция insert возник бы dead lock?
Зависит от того что за инсерт. Если Insert/select — да, возможен.
L>вопрос 2: если бы в хранимке была лишь одна инструкция update(причем каждый поток апдейтит уникальную запись) возник бы dead lock?
Зависит от того что за запрос. В общем случае — да, взаимоблокировка в этом случае возможна.
Re[5]: многопоточность и deadlock в mssql2000
От:
Аноним
Дата:
15.06.06 18:37
Оценка:
Здравствуйте, _d_m_, Вы писали:
___>Здравствуйте, BlackTigerAP, Вы писали:
BTA>>2 _d_m_:
BTA>>Ага, по таким вот "сериализаторавщикам" даже на Channel9 прошлись люди из МС. После таких деятелей и рождаются мифы о нежизнеспособности приложений на SQLServer, и заказчики плюются и проклинают тот день и час, когда связались с SQLServer и уходят на Oracle.
___>По каким таким? Что ты вообще обо мне знаешь? ___>Нет, наоборот. Мифы о нежизнеспособности SQLServer рождаются, когда некомпетентные в этих вопросах люди советуют блокировать таблицами. Мои клиенты себя чуствуют комфортно в том числе благодаря грамотно поставленным уровням изоляции. 99.9% запросов курят read commited и лишь уровень некоторых единичных запросов, там где это действительно необходимо — повышен до serializable.
А также некритичные отчеты на hint nolock (клиенты чувствуют себя комфортно в меру загруженности сервака).
Да и maxdop 1 в большинстве случаев повышает производительность. (не знаю, как на более, чем двух (чеырех с HS)).
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, _d_m_, Вы писали:
___>>Здравствуйте, BlackTigerAP, Вы писали:
BTA>>>2 _d_m_:
BTA>>>Ага, по таким вот "сериализаторавщикам" даже на Channel9 прошлись люди из МС. После таких деятелей и рождаются мифы о нежизнеспособности приложений на SQLServer, и заказчики плюются и проклинают тот день и час, когда связались с SQLServer и уходят на Oracle.
___>>По каким таким? Что ты вообще обо мне знаешь? ___>>Нет, наоборот. Мифы о нежизнеспособности SQLServer рождаются, когда некомпетентные в этих вопросах люди советуют блокировать таблицами. Мои клиенты себя чуствуют комфортно в том числе благодаря грамотно поставленным уровням изоляции. 99.9% запросов курят read commited и лишь уровень некоторых единичных запросов, там где это действительно необходимо — повышен до serializable.
А>А также некритичные отчеты на hint nolock (клиенты чувствуют себя комфортно в меру загруженности сервака). А>Да и maxdop 1 в большинстве случаев повышает производительность. (не знаю, как на более, чем двух (чеырех с HS)).
А>Michail Chernobrovov.
hint nolock — спорно. А вот в 2005-ом появилась прикольная возможность — опция базы READ_COMMITTED_SNAPSHOT. Вот это весчь.
Здравствуйте, DemAS, Вы писали:
DemAS>>>> Как вообще может возникнуть deadlock при работе с одним (и только одним) ресурсом ?
BTA>>Лёгко!!! Достаточно вспомнить, что для SQLServer является "блокируемым ресурсом". Для танкистов — запись.
DAS> Ок. А теперь приведи пример работы, когда два процесса работая с одной записью взаимноблокируют друг друга.
Пример:
/*
CREATE TABLE Test (Id int)
INSERT Test VALUES (1)
*/BEGIN TRAN
SELECT Id FROM Test(HOLDLOCK) WHERE Id = 1
WAITFOR DELAY '00:00:10'
UPDATE Test
SET Id = 1
WHERE Id = 1
COMMIT
Работают с одной записью, дэдлок возникает, условие выполнено
Здравствуйте, MoZ, Вы писали:
MoZ>Здравствуйте, DemAS, Вы писали:
DemAS>>>>> Как вообще может возникнуть deadlock при работе с одним (и только одним) ресурсом ?
BTA>>>Лёгко!!! Достаточно вспомнить, что для SQLServer является "блокируемым ресурсом". Для танкистов — запись.
DAS>> Ок. А теперь приведи пример работы, когда два процесса работая с одной записью взаимноблокируют друг друга. MoZ>Пример: MoZ>
MoZ>/*
MoZ>CREATE TABLE Test (Id int)
MoZ>INSERT Test VALUES (1)
MoZ>*/
MoZ>BEGIN TRAN
MoZ>SELECT Id FROM Test(HOLDLOCK) WHERE Id = 1
MoZ>WAITFOR DELAY '00:00:10'
MoZ>UPDATE Test
MoZ> SET Id = 1
MoZ>WHERE Id = 1
MoZ>COMMIT
MoZ>
MoZ>Работают с одной записью, дэдлок возникает, условие выполнено
Здравствуйте, _d_m_, Вы писали:
MoZ>>Работают с одной записью, дэдлок возникает, условие выполнено
___>Дэдлок не возникает. Т.к. это не дэдлок.
А что же это?
Server: Msg 1205, Level 13, State 54, Line 1
Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
Каким образом проверяли? В условии было сказано —
два процесса работая с одной записью взаимноблокируют друг друга
Здравствуйте, MoZ, Вы писали:
MoZ>>>Работают с одной записью, дэдлок возникает, условие выполнено
___>>Дэдлок не возникает. Т.к. это не дэдлок.
MoZ>А что же это? MoZ> MoZ>Server: Msg 1205, Level 13, State 54, Line 1 MoZ>Transaction (Process ID 53) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. MoZ>
Взаимоблокировка, как можно понять из названия – это ситуация, когда транзакции блокируют друг друга таким образом, что дальнейшее выполнение невозможно. В силу протокола двухфазной блокировки ни одна из участвующих во взаимоблокировке транзакций не может отпустить уже захваченные ей ресурсы до того, как наложит блокировки на все, что ей необходимо. А получить все необходимые ресурсы мешают уже наложенные блокировки. Таким образом, получается замкнутый круг. Естественно, и транзакций, и объектов в общем случае может быть сколь угодно много. Разорвать такую блокировку без внешнего вмешательства невозможно, и если не предпринимать специальных усилий, то транзакции будут находиться в состоянии ожидания бесконечно долго. Разрешить подобную ситуацию можно лишь путем отмены хотя бы одной из транзакций.
MoZ>Каким образом проверяли? В условии было сказано —
два процесса работая с одной записью взаимноблокируют друг друга
— так и проверяли, запускали два процесса?
Для каждого соединения MS SQL создает процесс — не путать с процессами ОС.
из этой статьи — это практически тот же пример, что пивел MoZ. Так что он полностью прав это классический дедлок, причем один из самых распространенных случаев, как практика показывает.
из этой статьи — это практически тот же пример, что пивел MoZ. Так что он полностью прав это классический дедлок, причем один из самых распространенных случаев, как практика показывает.
Да, приношу извинения. Не заметил хинт holdlock в исходном посте.
Здравствуйте, SergPas, Вы писали:
SP>блокировки со строки до страницы и так до таблицы в целом. После чего вероятность deadlock возрастает.
Наоборот. Вероятность блокировки других транзакций возрастает, а deadlock — уменьшается.
Здравствуйте, GlebZ, Вы писали:
GZ>Наоборот. Вероятность блокировки других транзакций возрастает, а deadlock — уменьшается.
Тут вообще нельзя однозначно утверждать, все зависит от запросов, структуры таблиц и распределения данных — может как увеличить вероятность дедлока так и уменьшить.
Здравствуйте, IB, Вы писали:
IB>Тут вообще нельзя однозначно утверждать, все зависит от запросов, структуры таблиц и распределения данных — может как увеличить вероятность дедлока так и уменьшить.
Конечно. Но где-то видел даже доказательства, что чем выше гранулярность блокировки, тем ниже вероятность взаимоблокировок при том же уровне конкуренции за общие ресурсы.
Здравствуйте, GlebZ, Вы писали:
GZ>Конечно. Но где-то видел даже доказательства, что чем выше гранулярность блокировки, тем ниже вероятность взаимоблокировок при том же уровне конкуренции за общие ресурсы.
Доказательства вряд ли, а вот конкретный пример — запросто, я в статье (http://rsdn.ru/?article/db/deadlocks.xml#E6KAE