Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 блокировка таблицы  [new]
Tdmitry
Member

Откуда: Москва
Сообщений: 78
Доброго всем дня!
Подскажите, люди добрые, как заблокировать выполнение транзакции, если выполняется еще предыдущая?

разработчиком был написан скрипт, в котором присутствует вот такие строки
  
begin tran
  /* Блокируем ID_VALUES для этой таблицы, пока не завершится транзакция, паралельное выполнение аналогичной транзакции будет заблокировано до окончания текущей*/

update ID_VALUES set LAST_VALUE = LAST_VALUE  where KEY_NAME = 'data_hospitaliz_adm_room'

далее нав-е не важно, но все же на вский случай
update motconsu
set ev_close=1, ev_date_close=:%AF_CURRENT_MOTCONSU_DATE, zapis_zakr_vayhaq_sob_tie=1
where motconsu_id=@List

   /*Получаем минимальный пустой номер счетчика*/
  select top 1 @MaxCardNumber=isnull(DH_CURR.MED_KARTA_STAC_SHETHIK,43000) + 1
  from {R}[T]DATA_HOSPITALIZ_ADM_ROOM DH_CURR
  left join {R}[T]DATA_HOSPITALIZ_ADM_ROOM DH_NEXT on (DH_NEXT.MED_KARTA_STAC_SHETHIK=DH_CURR.MED_KARTA_STAC_SHETHIK+1 and isnull(DH_NEXT.OTKAZAT_V_GOSPITALIZACII,0) <> 1)
  left join MOTCONSU M on M.MOTCONSU_ID=DH_CURR.MOTCONSU_ID
      where 
        isnull(DH_CURR.MED_KARTA_STAC_SHETHIK, 0)>0 and  isnull(DH_CURR.OTKAZAT_V_GOSPITALIZACII,0) <> 1
        and M.MOTCONSU_ID=M.MOTCONSU_EV_ID and M.MOTCONSU_EVENT_TYPES_ID in (11,14) and isnull(DH_NEXT.MED_KARTA_STAC_SHETHIK,0) =0 AND DH_CURR.MED_KARTA_STAC_SHETHIK>42999
    order by DH_CURR.MED_KARTA_STAC_SHETHIK
 
declare @FormedNum as varchar(100)
set @FormedNum = 
	(convert(varchar,@MaxCardNumber) + '-' +
	substring (convert (varchar (4), year (getdate()), 4), 3, 2) + ' С' )


/*Обновить данные таблицы "Госпитализация приемного отделения" в записи открывающей событие*/
      update {R}[T]DATA_HOSPITALIZ_ADM_ROOM set
         MED_KARTA_STAC_SHETHIK = @MaxCardNumber,
         NAPR_V_OTDELENIE=:@{R}[T]DATA_HOSPITALIZ_ADM_ROOM.NAPR_V_OTDELENIE,
         VID_STACIONARA=(select VID_STACIONARA from {R}[T]DATA_HOSPITALIZ_ADM_ROOM where data123_id = :@{R}[T]DATA_HOSPITALIZ_ADM_ROOM.data123_id), 
         OTDELENIE=(select FM_DEP.FM_DEP_ID from MOTCONSU
                                      JOIN {R}[T]HO_RESERV ON {R}[T]MOTCONSU.MOTCONSU_ID = {R}[T]HO_RESERV.MOTCONSU_CREATE_ID 
                                      JOIN {R}[T]FM_DEP ON {R}[T]FM_DEP.FM_DEP_ID = {R}[T]HO_RESERV.FM_DEP_ID 
                                   where {R}[T]motconsu.motconsu_id=:@{R}[T]MOTCONSU.MOTCONSU_ID and {R}[T]HO_RESERV.RES_STATE <>'A')
      where data123_id = @Data_id 

/*Обновить данные таблицы "История заболевания" в записи, открывающей событие*/
      update motconsu set 
         motconsu_event_types_id = :EV_TYPE, /*Входной параметр, определяющий тип открываемого события*/
         gospitalizirovan = 1,
         ev_gosp = 1, 
         ev_name = (case :EV_TYPE when 11 then 'Госпитализация' when 14 then 'Роддом' end + ' / ' +
                              (select {R}[T]fm_dep.label from {R}[T]DATA_HOSPITALIZ_ADM_ROOM 
                                  join {R}[T]motconsu on {R}[T]motconsu.motconsu_id={R}[T]DATA_HOSPITALIZ_ADM_ROOM.motconsu_id
                                  join {R}[T]fm_dep on {R}[T]DATA_HOSPITALIZ_ADM_ROOM.otdelenie={R}[T]fm_dep.fm_dep_id
                               where {R}[T]motconsu.motconsu_id = ISNULL(:@{R}[T]MOTCONSU.MOTCONSU_EV_ID,:@{R}[T]MOTCONSU.MOTCONSU_ID)) + ' ' +
                             (convert (varchar (10), (select DATA_I_VREMQ_POSTUPLENIQ from {R}[T]DATA_HOSPITALIZ_ADM_ROOM where {R}[T]DATA_HOSPITALIZ_ADM_ROOM.motconsu_id =:@{R}[T]MOTCONSU.MOTCONSU_EV_ID), 104) ) +
                              case :EV_TYPE when 11 then ' ИБ' when 14 then ' ИР' end + @FormedNum 
                              /*(select {R}[T]DATA_HOSPITALIZ_ADM_ROOM.NOMER_ISTORII_BOLEZNI from {R}[T]DATA_HOSPITALIZ_ADM_ROOM
                                 join {R}[T]motconsu on {R}[T]motconsu.motconsu_id={R}[T]DATA_HOSPITALIZ_ADM_ROOM.motconsu_id 
                              where {R}[T]motconsu.motconsu_id =ISNULL(:@{R}[T]MOTCONSU.MOTCONSU_EV_ID,:@{R}[T]MOTCONSU.MOTCONSU_ID) )*/)
       where {R}[T]motconsu.motconsu_id = ISNULL(:@{R}[T]MOTCONSU.MOTCONSU_EV_ID,:@{R}[T]MOTCONSU.MOTCONSU_ID)
commit

так вот, тут выбирается первый свободный номер и присваивается вновь созданной истории. при этом все это дело выполняется секунд 5, и если запустить скрипт с несольких рабочих мест в течение этих 5 секунд, то всем новым историям присваивается один и тот же номер. вероятно блокировка не работает. своими силами уже 3 часа ничего не получается, надеюсь на помощь
26 окт 13, 12:55    [15035928]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34621
Tdmitry,

update ID_VALUES set LAST_VALUE = LAST_VALUE where KEY_NAME = 'data_hospitaliz_adm_room'

Тут запись блокируется, но значение ключа не меняется и не выбирается. Где это происходит?
26 окт 13, 17:51    [15036227]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31444
Tdmitry
вероятно блокировка не работает. своими силами уже 3 часа ничего не получается, надеюсь на помощь
Лучше использовать SELECT с хинтами, а не UPDATE

А ещё лучше для таких целей использовать sp_getapplock; у вас, как я понимаю, просто самодельная реализация этой процедуры.
26 окт 13, 20:08    [15036453]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
Tdmitry
Member

Откуда: Москва
Сообщений: 78
Спасибо за ответы!
Почитаю, что такое хинты, и процедуру посмотрю.
Значение LAST_VALUE в таблице ID_VALUES меняется при добавлении строки в DATA_HOSPITALIZ_ADM_ROOM

Пока что в конце написал кажется вот так
if(exists(select top 1 * from DATA_HOSPITALIZ_ADM_ROOM where NOMER_ISTORII_BOLEZNI=@FormedNum))
  begin
  waitfor delay '00:01';
  rollback
  end
else commit


Не знаю насколько, это правильно, но пока работает, ситуация была довольно экстренная.
Не совсем понял почему, но если не писать waitfor delay '00:01', то rollback не откатывает транзакцию
28 окт 13, 09:02    [15039511]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31444
Tdmitry
Не совсем понял почему, но если не писать waitfor delay '00:01', то rollback не откатывает транзакцию
Должен откатывать и без waitfor delay... Сообщение об ошибке было какое то?
28 окт 13, 09:04    [15039519]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
Tdmitry
Member

Откуда: Москва
Сообщений: 78
не было ошибки
в условии вместо @FormedNum ставил существующий номер, хотел зациклить транзакцию. С waitfor зациклился, а без просто взял и присвоил следующий номер как будто и нет rollback'а
28 окт 13, 09:57    [15039700]     Ответить | Цитировать Сообщить модератору
 Re: блокировка таблицы  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31444
Tdmitry
в условии вместо @FormedNum ставил существующий номер, хотел зациклить транзакцию. С waitfor зациклился, а без просто взял и присвоил следующий номер как будто и нет rollback'а
Ну, значит код неправильный, а не просто "если не писать waitfor delay". Что то ещё менялось.
28 окт 13, 10:38    [15039847]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить