Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Как лучше выбрать блокировку, правильно управлять транзакциями / 11 сообщений из 11, страница 1 из 1
31.10.2001, 09:55
    #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
01.11.2001, 12:55
    #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
01.11.2001, 14:38
    #32016424
Владимир Смирнов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше выбрать блокировку, правильно управлять транзакциями
При выборке данных используйте запрос типа
SELECT ... FROM XXX WITH (NOLOCK) WHERE ...
Только при этом учитывайте, что данные, полученные во время чтения, могут не соответствовать тем данным, которые будут в таблице после завершения выполняемой в этот момент транзакции, изменяющей эти самые данные (если это не важно, то можно пренебречь).
...
Рейтинг: 0 / 0
02.11.2001, 08:05
    #32016450
__Roman
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше выбрать блокировку, правильно управлять транзакциями
TABLOCK совершенно необходим только тогда, когда нужно на некоторое время запретить другим транзакциям вставки/удаления из таблицы (нужно ли это вам на самом деле?) или блокируемых записей очень много.
Если надо запретить обновление/удаление конкретных записей, лучше используйте PAGLOCK или даже ROWLOCK.
HOLDLOCK - заставляет сервер держать блокировку вплоть до завершения транзакции.

Кроме того, вместо SELECT @ins_error = @@ERROR лучше писать SET @ins_error = @@ERROR.
Насчет SET LOCK_TIMEOUT 10000: если надо сказать серверу, что при наличии блокировки
надо не ждать, а сразу прекратить выполнение стейтмента, укажите перед началом транзакции SET LOCK_TIMEOUT 0
...
Рейтинг: 0 / 0
06.11.2001, 11:24
    #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
09.11.2001, 13:53
    #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
09.11.2001, 19:19
    #32016789
Garya
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как лучше выбрать блокировку, правильно управлять транзакциями
Deadlock на голом месте не возникает. Процесс1 блокирует ресурс1 и запрашмвает ресурс2. Процесс2 блокирует ресурс2 и запрашивает ресурс1. Оба сидят с заблокированными ресурсами и ждут, когда другой процесс освободит свои. Это и есть deadlock. Если при написании скриптов все хранимые процедуры и триггеры блокируют ресурсы в одной и той же последовательности, deadlock происходить не должен. Проверь тексты триггеров и хранимых процедур.
...
Рейтинг: 0 / 0
12.11.2001, 12:40
    #32016850
Как лучше выбрать блокировку, правильно управлять транзакциями
Garya, насчет одной и той же последовательности ерунду говоришь.

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

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

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

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


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