powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как лучше выбрать блокировку, правильно управлять транзакциями
11 сообщений из 11, страница 1 из 1
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016325
Фотография Сашенька
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемые профи!

Подскажите пример девушке, осваивающей 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, а эта технологя не допускает явное определение начала транзакции (:
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016409
OlegDez
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Клиент номер один:
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

надеюсь, что это поможет, хотя за правильность не ручаюсь - чайник я :о)
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016424
Владимир Смирнов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
При выборке данных используйте запрос типа
SELECT ... FROM XXX WITH (NOLOCK) WHERE ...
Только при этом учитывайте, что данные, полученные во время чтения, могут не соответствовать тем данным, которые будут в таблице после завершения выполняемой в этот момент транзакции, изменяющей эти самые данные (если это не важно, то можно пренебречь).
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016450
__Roman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TABLOCK совершенно необходим только тогда, когда нужно на некоторое время запретить другим транзакциям вставки/удаления из таблицы (нужно ли это вам на самом деле?) или блокируемых записей очень много.
Если надо запретить обновление/удаление конкретных записей, лучше используйте PAGLOCK или даже ROWLOCK.
HOLDLOCK - заставляет сервер держать блокировку вплоть до завершения транзакции.

Кроме того, вместо SELECT @ins_error = @@ERROR лучше писать SET @ins_error = @@ERROR.
Насчет SET LOCK_TIMEOUT 10000: если надо сказать серверу, что при наличии блокировки
надо не ждать, а сразу прекратить выполнение стейтмента, укажите перед началом транзакции SET LOCK_TIMEOUT 0
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016628
Oleg F
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Блокировки применять в случае необходимости, а не просто так. В подавляющем большинстве случаев никакие дополнительные хинты, управляющие блокировками, не нужны. SQL Server и так всё сделает правильно. Например, команда UPDATE одной строки (если она сделана внутри транзакции) заблокирует строку до конца транзакции сама, без всяких дополнительных подсказок. По-другому UPDATE просто не может работать. Хинты, регулирующие блокировки, имеет смысл использовать только в SELECT-е (например, если нужно сделать "грязное" чтение (NOLOCK) или заблокировать строку, взяв её на редактирование)

2. Поскольку все ресурсы, заблокированные внутри транзакции, блокируются до окончания транзакции, нужно строить клиентскую программу так, чтоб она использовала короткие транзакции. Т.е. от BEGIN TRANSACTION до COMMIT TRANSACTION должны проходить секунды, а не минуты.
Но это в том случае, если блокируется много строк в разных таблицах. В противном случае см. пункт 3.

3. Если нужно заблокировать строку, а потом пользователь будет долго чесать репу и думать, как лучше её отредактировать, то нужно сделать так:

BEGIN TRANSACTION
SELECT .... WITH (UPDLOCK HOLDLOCK)
-- пользователь думает, редактирует,
-- никто другой до конца транзакции не может блокировать эту строку
UPDATE .... -- сохраняет изменения после редактирования
COMMIT TRANSACTION
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016761
Vladimir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ох, как давно я хотел поговорить на эту тему, да вот только времени небыло.
Скажу сразу, что все что писалось выше правильно, но это все работает видимо в простых случаях (буду рад, если многоуважаемый пипл не согласиться и научит меня дурака, как правильно работать с блокировками). У меня такая ситуация (работаю в 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и.
Могете попинать, посмеятся, но только помогите мне.
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016789
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Deadlock на голом месте не возникает. Процесс1 блокирует ресурс1 и запрашмвает ресурс2. Процесс2 блокирует ресурс2 и запрашивает ресурс1. Оба сидят с заблокированными ресурсами и ждут, когда другой процесс освободит свои. Это и есть deadlock. Если при написании скриптов все хранимые процедуры и триггеры блокируют ресурсы в одной и той же последовательности, deadlock происходить не должен. Проверь тексты триггеров и хранимых процедур.
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016850
Garya, насчет одной и той же последовательности ерунду говоришь.

Классический (для MSSQL) дидлок:
begin tran
select .. from table1 (holdlock)
....
update table1 ...
commit

этот запрос, запущенный в двух коннектах, обязательно вызовет дидлок, надо тока успеть во втором коннекте сделать селект до того, как в первом произойдет апдейт.
Этот дидлок лечиться дополнительной простановкой updlock в селекте.
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016856
Vladimir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хм... С UPDLOCK идея интересная попробую.
Я вообще-то думал, что NOLOCK заставляет сервер не смотреть на блокировки, ули я просто запрашиваю данные. :-0
А может еще тогда объесните как писать хинты, я вот их набухал в запрос столько сколько таблиц, а похоже, что хинты можно комбинировать определенным образом даже для одной таблицы.
А на счет процедур. тут все нормально, т.к. в данном месте они вообще не работают. Ситуация-то элементарная:
первый клиент делает
connection.begintrans -- начало транзакции
append...
<N-ное кол-во времени проходит> -- (*)
connection.committrans -- конец транзакции
второй клиент во время (*) делает тот SELECT, который я и писал.
Вот второй клиент и ждет пока первый сделает свое дело, а т.к. время ожидания у меня не бесконечно, то возникает ошибка по TIMEOUTу. Может я, просто не правильно выразился в прошлом письме, тогда прошу ПАРДОНУ
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016875
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Бухать хинты куда ни попадя лучше поостеречься. SQL server достаточно грамотно управляет блокировками, чтобы ему постоянно подсказывать, особенно если до конца не разобрался сам, как же он их должен делать. Рекомендую хинты использовать только в самых специфических ситуациях, которые требуют особого режима обработки и не допускают никаких других.
Блокировка и дедлок - вещи действительно разные. Дедлок - это определенная совокупность блокировок, которые заводят несколько транзакций в тупик, который может быть устранен только откатом одной из транзакций с освобождением занятых ею ресурсов. А просто блокировка, пусть и продолжительная по времени - это еще не тупик.
Чтобы не отваливаться по таймауту, нужно выставить параметр CommandTimeOut объекта ADODB.Command при его создании. Если Command генерится динамически (команда задается через свойства Connection), то это сделать не получится - оно будет равно 30 секундам (почему я предпочитаю явно сам создавать все объекты ADO и завязывать их самостоятельно друг на друга).

2Глеб Уфимцев. Приведенный тобой пример приводит к последовательному блокированию одного ресурса разными типами блокировки. Аналогичные проблемы могут возникнуть и при эскалации блокировок. Например, при переходе блокировки с уровня строки на уровень страницы с блокированием данных (строк, граничащих с запрошенными), которые пытается заблокировать другая транзакция. Так что, скорее всего ты прав. Подобные проблемы с высокой степенью вероятностью обходятся соблюдением двух правил:
1. Соблюдением одной и той же последовательности обращения к ресурсам (например, к таблицам).
2. Воздержанием от использования экзотических хинтов.
Соблюдение этих двух правил позволит по крайней мере в 99% случаев новичкам избегать дедлоков. Ну а уж ежели нахинтили, так напрягайте мозги и вникайте в дебри возможных последствий (что даже для семипядевых во лбу может оказаться не по силам, если скриптов множество и пересекаться они могут в великом множестве комбинаций).
...
Рейтинг: 0 / 0
Как лучше выбрать блокировку, правильно управлять транзакциями
    #32016884
Фотография Сашенька
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так что же получается: лучше вообще не использовать хинты и set transaction isolation level ?
Соблюдение одной и той же последовательности обращения к таблицам - это значит так:
в одной процедуре обращаюсь к таблице А, затем к таблице Б
в другой процедуре в той же последовательности ?

Можно есчё 100%-примерчик кода на тему блокировок и транзакций???
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как лучше выбрать блокировку, правильно управлять транзакциями
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]