Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.05.21;
Скачать: CL | DM;

Вниз

Многопользовательская работа в среде MSSQL Server   Найти похожие ветки 

 
_Anton   (2006-03-22 19:16) [0]

Проблема довольно специфичная:
блокируется таблица в эксклюзивную блокировку до окончания
работы приложения.

подробно:
на главной форме есть ADOConnection, этот коннект передаётся
во все формы через свойство FConnection: TADOConnection

1. блокируем конкретную строку в SQL Query Analyzer
  так:

begin tran

 SELECT CNAME
 FROM   WH_Social.dbo.OWH_OrgType_tb WITH (UPDLOCK)
 WHERE  CNAME IN ("Банк")

2. открываем нашу форму с переданным через свойство  
  коннектом и пытаемся удалить эту строку вызовом  
  процедуры:

  CREATE PROCEDURE dbo.OWH_DeleteTypeOrg_sp
--
-- DESCRIPTION: Процедура удаления типа ППВ из справочника
--
-- for WH_Social
--
(
@p_TypeOrgName varchar(100)
)
AS
BEGIN

DECLARE @l_ErrCode INT

 IF @p_TypeOrgName IS NULL BEGIN
   SET @l_ErrCode = -1
   RAISERROR("Пустой параметр процедуры", 16, 1)
   GOTO FINAL
 END

 
 BEGIN TRANSACTION
 SAVE  TRANSACTION transp_DelTypeOrg

 DELETE FROM WH_Social.dbo.OWH_OrgType_tb
 WHERE CNAME = @p_TypeOrgName
 
 IF @@ERROR <> 0 OR @@ROWCOUNT <> 1 BEGIN
                                    SET @l_ErrCode = -2
                                    RAISERROR("Ошибка удаления", 16, 1)
                                    GOTO FINAL_TRAN
                                    END

FINAL_TRAN:
   IF @l_ErrCode <> 0 ROLLBACK TRANSACTION transp_DelTypeOrg
   COMMIT TRANSACTION

FINAL:
   RETURN(@l_ErrCode)
END

3. Истекает timeout ADOStoredProc.

4. делаем откат\коммит нашей транзакции в SQL Query Analyzer

5. теперь повторяем попытку удалить строку через форму.
   и видим, что строка удалена в нашей сесии.

6. после видим что вся таблица заблокирована приложением,
  причём разблокируется только по окончании его работы
 
7. по окончании работы приложения удалённая через форму  
   строка появляется в таблице.

буду очень признателен за разьяснения, перепробывал уже всё, что пришло на ум


 
Nikolay M. ©   (2006-03-22 19:38) [1]

1) Возможная причина эскалация эксклюзивной блокировки со строки до таблицы - в отсутствии индекса на CNAME или, что маловероятно, в слишком высоком уровне изоляции SERIALIZABLE.

2) Не понял сакральный смысл такой ХП (зачем нужна транзакция, да еще с сейвпоинтом), но сразу вижу отсутствие инициализации @l_ErrCode, что может является причиной ролбэка в конце ХП.


 
Nikolay M. ©   (2006-03-22 19:52) [2]


> Nikolay M. ©   (22.03.06 19:38) [1]
> 1) Возможная причина эскалация

1) Возможная причина эскалациИ


 
Ega23 ©   (2006-03-22 19:58) [3]


> но сразу вижу отсутствие инициализации @l_ErrCode


Ну да, как минимум после As Begin надо поставить Set @l_ErrCode=0


 
_Anton   (2006-03-23 11:01) [4]

- инициализация @l_ErrCode здесь не при чём, можно и без неё;
- индекс по CNAME может и нужен, но там словарная таблица из двух
 столюцов, такие таблицы в ORACLE организуют по индексу, а в MS не  
 знаю, можно ли так;
- явное написание транзакции в процедуре осталось у меня после её  
 правки, там ещё были операторы;

Решил проблему:
- перенёс явное управление транзакцией из процедуры в форму, всё  
 заработало;


 
Ega23 ©   (2006-03-23 11:44) [5]


> - инициализация @l_ErrCode здесь не при чём, можно и без
> неё;


Я бы не стал так категорично утверждать.
Набери в QA следующий код:
Declare @X int
Select X=@X


И выполни.


 
Nikolay M. ©   (2006-03-23 14:06) [6]


> - инициализация @l_ErrCode здесь не при чём, можно и без
> неё;
> - индекс по CNAME может и нужен, но там словарная таблица
> из двух
>  столюцов, такие таблицы в ORACLE организуют по индексу,
>  а в MS не  
>  знаю, можно ли так;


Инициализация переменной нужна - это раз.
Не знаю, что такое "словарная таблица из 2 столбцов", но если индекса по CNAME нет, то я правильно указал причину эксклюзивной блокировки на всю таблицу - это два.
Ну и, наконец, мое непокобелимое имхо заключается в том, что управление транзакциями с клиента неверно идеологически - это три.


 
_Anton   (2006-03-23 16:00) [7]

:)
да знаю я что NULL без инициализации

индекс я тоже само собой добавил,
а на счет управления транзакциями с клиента -
например без этого не обойтись при select for update

спасибо всем


 
Ega23 ©   (2006-03-23 16:34) [8]


> да знаю я что NULL без инициализации


А раз знаешь, то посмотри внимательно на свою процедуру и назови тот случай, когда у тебя Commit Tran произойдёт.

IF @l_ErrCode <> 0 ROLLBACK TRANSACTION transp_DelTypeOrg
  COMMIT TRANSACTION


 
_Anton   (2006-03-23 16:47) [9]

sorry


 
Nikolay M. ©   (2006-03-23 16:59) [10]


> Ega23 ©   (23.03.06 16:34) [8]
> А раз знаешь, то посмотри внимательно на свою процедуру
> и назови тот случай, когда у тебя Commit Tran произойдёт.
>
>
> IF @l_ErrCode <> 0 ROLLBACK TRANSACTION transp_DelTypeOrg
>   COMMIT TRANSACTION


Очевидно, при

SET ANSI_NULLS OFF.


 
Ega23 ©   (2006-03-23 17:02) [11]


> SET ANSI_NULLS OFF.


Не вижу явного объявления.  :о)


 
Nikolay M. ©   (2006-03-23 17:11) [12]


> Ega23 ©   (23.03.06 17:02) [11]
> > SET ANSI_NULLS OFF.
> Не вижу явного объявления.  :о)


Так именно поэтому у него запись и не удаляется :))))


 
_Anton   (2006-03-23 19:20) [13]

ни индекс, ни SET ANSI_NULLS OFF не помогли;
дело всё-таки в ADO

честно говоря на счет помощи в этом деле индекса я сомневался,
знаю, что эскалация происходит при неиндексировании внешних ключей (опять же в oracle), а насчёт одной таблицы - ничего не слышал,
хотя чем Microsoft не шутит

CREATE  PROCEDURE dbo.OWH_DeleteTypeOrg_sp
--
-- DESCRIPTION: Процедура удаления типа ППВ из справочника
--
-- for WH_Social
--
(
@p_TypeOrgName varchar(100)
)
AS
BEGIN
SET ANSI_NULLS OFF

DECLARE @l_ErrCode INT

SET     @l_ErrCode=0

 IF @p_TypeOrgName IS NULL BEGIN
   SET @l_ErrCode = -1
   RAISERROR("Пустой параметр процедуры", 16, 1)
   GOTO FINAL
 END

 
 BEGIN TRANSACTION
 SAVE  TRANSACTION transp_DelTypeOrg

 DELETE FROM WH_Social.dbo.OWH_OrgType_tb
 WHERE CNAME = @p_TypeOrgName
 
 IF @@ERROR <> 0 OR @@ROWCOUNT <> 1 BEGIN
                                    SET @l_ErrCode = -2
                                    RAISERROR("Ошибка удаления", 16, 1)
                                    --GOTO FINAL_TRAN
                                    END

FINAL_TRAN:
   IF @l_ErrCode <> 0 ROLLBACK TRANSACTION transp_DelTypeOrg
   COMMIT TRANSACTION

FINAL:
   RETURN(@l_ErrCode)
END
GO


 
Nikolay M. ©   (2006-03-23 19:32) [14]


> _Anton   (23.03.06 19:20) [13]
> ни индекс, ни SET ANSI_NULLS OFF не помогли;


А селективность поля какая? Т.е. сколько уникальных записей и сколько всего записей в таблице?
Если таблица большая, а значения в поле, скажем, только "0" и "1", то индекс тут не поможет, при выборке с хинтом UPDLOCK в незакрытой транзакции потребуется сканирование таблицы, что тоже может привести к блокировке таблицы.
Хотя, честно говоря, устал я гаданиями на кофейной гуще заниматься. Готовые скрипты и данные в студию.


 
_Anton   (2006-03-24 12:02) [15]

:)
если бы в столбце были "1" и "0", то не проще построить bitmap?

ещё раз спасибо всем, вопрос считаю снятым


 
Nikolay M. ©   (2006-03-24 15:45) [16]


> _Anton   (24.03.06 12:02) [15]
> если бы в столбце были "1" и "0", то не проще построить
> bitmap?


Есть таблица неких сущностей, у каждой есть признак Enabled/Disabled, т.е. 0/1. Какую маску ты собрался строить?



Страницы: 1 вся ветка

Текущий архив: 2006.05.21;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.062 c
15-1145856864
ilya39
2006-04-24 09:34
2006.05.21
Proxy


15-1145624942
oldman
2006-04-21 17:09
2006.05.21
Надо заполнить таблицу. Очень надо! :(


2-1146238797
Khim
2006-04-28 19:39
2006.05.21
почтовой клиент, ошибка: Authentication falled


15-1145890224
yaro
2006-04-24 18:50
2006.05.21
Автоматический пернос данных в таблицу


2-1146867723
tanya11
2006-05-06 02:22
2006.05.21
направление кнопки