Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Уважаемые профи! Подскажите пример девушке, осваивающей SQL2000, как лучше разрулить транзакциями и блокировками ситуацию, чтобы выполнялись следующие изменения в важной таблице ХХХ как ЕДИНОЕ ЦЕЛОЕ, при этом была возможность ВЫБОРКИ данных другими пользователями из этой же таблицы ХХХ, например : DECLARE @upd_error int, @ins_error int BEGIN TRANSATION UPDATE ХХХ SET nLft=100 WITH (TABLOCK, HOLDLOCK) WHERE nLft>10 SELECT @upd_error = @@ERROR INSERT INTO ХХХ (Fname) VALUES ('Bob') SELECT @ins_error = @@ERROR IF @upd_error = 0 AND @ins_error = 0 COMMIT TRANSACTION ELSE ROLLBACK TRAN Я запуталась - какие оптимальны хинты TABLOCK HOLDLOCK или установка перед началом транзакции SET TRANSACTION ISOLATION LEVEL REPEATABLE READ | SERIALIZABLE Для избежания долгой блокировки лучше ещё указать SET LOCK_TIMEOUT 10000 -- например К тому же возможно доступ к базе будет через ODBC, а эта технологя не допускает явное определение начала транзакции (: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.10.2001, 09:55 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Клиент номер один: select * from t1 with (rowlock, holdlock) where id = 1 begin tran update t1 set field1 = 'someData' where id = 1 --any other operations-- commit а в это время (пока не сделан COMMIT) некто клиент номер 2: set transaction isolation level read uncommited begin tranasaction update t1 set field1 = 'someOtherData' where id = 1 --и будет ждать, пока не завершиться другая операция ... в то же время клиент2 может видеть несохранённые данные в таблице t1 надеюсь, что это поможет, хотя за правильность не ручаюсь - чайник я :о) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2001, 12:55 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
При выборке данных используйте запрос типа SELECT ... FROM XXX WITH (NOLOCK) WHERE ... Только при этом учитывайте, что данные, полученные во время чтения, могут не соответствовать тем данным, которые будут в таблице после завершения выполняемой в этот момент транзакции, изменяющей эти самые данные (если это не важно, то можно пренебречь). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.11.2001, 14:38 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
TABLOCK совершенно необходим только тогда, когда нужно на некоторое время запретить другим транзакциям вставки/удаления из таблицы (нужно ли это вам на самом деле?) или блокируемых записей очень много. Если надо запретить обновление/удаление конкретных записей, лучше используйте PAGLOCK или даже ROWLOCK. HOLDLOCK - заставляет сервер держать блокировку вплоть до завершения транзакции. Кроме того, вместо SELECT @ins_error = @@ERROR лучше писать SET @ins_error = @@ERROR. Насчет SET LOCK_TIMEOUT 10000: если надо сказать серверу, что при наличии блокировки надо не ждать, а сразу прекратить выполнение стейтмента, укажите перед началом транзакции SET LOCK_TIMEOUT 0 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.11.2001, 08:05 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
1. Блокировки применять в случае необходимости, а не просто так. В подавляющем большинстве случаев никакие дополнительные хинты, управляющие блокировками, не нужны. SQL Server и так всё сделает правильно. Например, команда UPDATE одной строки (если она сделана внутри транзакции) заблокирует строку до конца транзакции сама, без всяких дополнительных подсказок. По-другому UPDATE просто не может работать. Хинты, регулирующие блокировки, имеет смысл использовать только в SELECT-е (например, если нужно сделать "грязное" чтение (NOLOCK) или заблокировать строку, взяв её на редактирование) 2. Поскольку все ресурсы, заблокированные внутри транзакции, блокируются до окончания транзакции, нужно строить клиентскую программу так, чтоб она использовала короткие транзакции. Т.е. от BEGIN TRANSACTION до COMMIT TRANSACTION должны проходить секунды, а не минуты. Но это в том случае, если блокируется много строк в разных таблицах. В противном случае см. пункт 3. 3. Если нужно заблокировать строку, а потом пользователь будет долго чесать репу и думать, как лучше её отредактировать, то нужно сделать так: BEGIN TRANSACTION SELECT .... WITH (UPDLOCK HOLDLOCK) -- пользователь думает, редактирует, -- никто другой до конца транзакции не может блокировать эту строку UPDATE .... -- сохраняет изменения после редактирования COMMIT TRANSACTION ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.11.2001, 11:24 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Ох, как давно я хотел поговорить на эту тему, да вот только времени небыло. Скажу сразу, что все что писалось выше правильно, но это все работает видимо в простых случаях (буду рад, если многоуважаемый пипл не согласиться и научит меня дурака, как правильно работать с блокировками). У меня такая ситуация (работаю в Delphi через ADO компоненты): - есть главная форма, где показан весь список клиентов, причем там показываются, где человек живет и какой у него тариф, понятно, что эти данные берутся из 2-х других таблиц; - надо добавить нового клиента, с адресом и тарифом, причем др. пользователь во время добавления может опять запросить список клиентов. Организую работу так: в главной форме ADOConnection+ADOQuery, а в форме, где добавляю нового клиента свои ADOConnection+ADOQuery. Так вот возникают deadlockи при любых комбинациях уровней изоляции, блокировок и хинтов. Правда я нашел решение через зад (как обычно) . Установил блокировку типа ltBatchOptimistic и тогда все заработало при любых комбинациях пока не зделать Post, т.е. запомнить данные. Мне все это не нравиться. Кстати, блокируются системой таблицы адресов и тарифов, а не клиентов. Может SELECT по другому надо написать? Я делаю так: SELECT a.Id_c, b.Name, c.Name FROM cust a,house b,tariff c WITH(NOLOCK, NOLOCK, NOLOCK) WHERE a.Id_house*=b.Id_house AND a.Id_traffic=c.Id_traffic Именно в этом запросе возникают DEADLOCKи. Могете попинать, посмеятся, но только помогите мне. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.11.2001, 13:53 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Deadlock на голом месте не возникает. Процесс1 блокирует ресурс1 и запрашмвает ресурс2. Процесс2 блокирует ресурс2 и запрашивает ресурс1. Оба сидят с заблокированными ресурсами и ждут, когда другой процесс освободит свои. Это и есть deadlock. Если при написании скриптов все хранимые процедуры и триггеры блокируют ресурсы в одной и той же последовательности, deadlock происходить не должен. Проверь тексты триггеров и хранимых процедур. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.11.2001, 19:19 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Garya, насчет одной и той же последовательности ерунду говоришь. Классический (для MSSQL) дидлок: begin tran select .. from table1 (holdlock) .... update table1 ... commit этот запрос, запущенный в двух коннектах, обязательно вызовет дидлок, надо тока успеть во втором коннекте сделать селект до того, как в первом произойдет апдейт. Этот дидлок лечиться дополнительной простановкой updlock в селекте. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2001, 12:40 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Хм... С UPDLOCK идея интересная попробую. Я вообще-то думал, что NOLOCK заставляет сервер не смотреть на блокировки, ули я просто запрашиваю данные. :-0 А может еще тогда объесните как писать хинты, я вот их набухал в запрос столько сколько таблиц, а похоже, что хинты можно комбинировать определенным образом даже для одной таблицы. А на счет процедур. тут все нормально, т.к. в данном месте они вообще не работают. Ситуация-то элементарная: первый клиент делает connection.begintrans -- начало транзакции append... <N-ное кол-во времени проходит> -- (*) connection.committrans -- конец транзакции второй клиент во время (*) делает тот SELECT, который я и писал. Вот второй клиент и ждет пока первый сделает свое дело, а т.к. время ожидания у меня не бесконечно, то возникает ошибка по TIMEOUTу. Может я, просто не правильно выразился в прошлом письме, тогда прошу ПАРДОНУ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2001, 13:09 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Бухать хинты куда ни попадя лучше поостеречься. SQL server достаточно грамотно управляет блокировками, чтобы ему постоянно подсказывать, особенно если до конца не разобрался сам, как же он их должен делать. Рекомендую хинты использовать только в самых специфических ситуациях, которые требуют особого режима обработки и не допускают никаких других. Блокировка и дедлок - вещи действительно разные. Дедлок - это определенная совокупность блокировок, которые заводят несколько транзакций в тупик, который может быть устранен только откатом одной из транзакций с освобождением занятых ею ресурсов. А просто блокировка, пусть и продолжительная по времени - это еще не тупик. Чтобы не отваливаться по таймауту, нужно выставить параметр CommandTimeOut объекта ADODB.Command при его создании. Если Command генерится динамически (команда задается через свойства Connection), то это сделать не получится - оно будет равно 30 секундам (почему я предпочитаю явно сам создавать все объекты ADO и завязывать их самостоятельно друг на друга). 2Глеб Уфимцев. Приведенный тобой пример приводит к последовательному блокированию одного ресурса разными типами блокировки. Аналогичные проблемы могут возникнуть и при эскалации блокировок. Например, при переходе блокировки с уровня строки на уровень страницы с блокированием данных (строк, граничащих с запрошенными), которые пытается заблокировать другая транзакция. Так что, скорее всего ты прав. Подобные проблемы с высокой степенью вероятностью обходятся соблюдением двух правил: 1. Соблюдением одной и той же последовательности обращения к ресурсам (например, к таблицам). 2. Воздержанием от использования экзотических хинтов. Соблюдение этих двух правил позволит по крайней мере в 99% случаев новичкам избегать дедлоков. Ну а уж ежели нахинтили, так напрягайте мозги и вникайте в дебри возможных последствий (что даже для семипядевых во лбу может оказаться не по силам, если скриптов множество и пересекаться они могут в великом множестве комбинаций). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.11.2001, 18:01 |
|
||
|
Как лучше выбрать блокировку, правильно управлять транзакциями
|
|||
|---|---|---|---|
|
#18+
Так что же получается: лучше вообще не использовать хинты и set transaction isolation level ? Соблюдение одной и той же последовательности обращения к таблицам - это значит так: в одной процедуре обращаюсь к таблице А, затем к таблице Б в другой процедуре в той же последовательности ? Можно есчё 100%-примерчик кода на тему блокировок и транзакций??? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.11.2001, 15:36 |
|
||
|
|

start [/forum/topic.php?fid=46&gotonew=1&tid=1825024]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
34ms |
get topic data: |
8ms |
get first new msg: |
5ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
2ms |
| others: | 232ms |
| total: | 356ms |

| 0 / 0 |
