|
|
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
подскажите решение следующей проблемы: Все общение с сервером построено исключительно на вызовах хранимых процедур. На стороне клиента присутствуют только операторы запуска этих хранимых процедур. Транзакции открываются и закрываются только в теле этих процедур. Код проверен - транзакции всегда закрываются. Иногда происходит "зависание" транзакции - программа из sp выходит без всяких ругательств, но транзакция остается открытой - естественно, в последствии все изменения, вносимые пользователем, будут утрачены при выходе из программы. Пробовал с этим бороться при входе в процедуру проверяя количество открытых транзакций - не получилось, возвращается единица, но при попытке закрыть транзпкцию - вылет по ошибке - нет открытых транзакций.... Наверняка я чего-то не понимаю, но вот чего!? И второй вопрос: как народ борется со следующей ситуацией: есть, например, такой код: BEGIN TRAN Select I_D, mName From tbl_Test IF @@error <> 0 BEGIN Rollback Tran Return END ELSE BEGIN COMMIT TRAN END при этом, если я изменю в таблице название поля, которое учавствует в select, то все вылетит по ошибке, и при этом никаких откатов не произойдет - транзакция останется открытой. Я конечно, понимаю, что менять названия поля нехорошо, но в процессе постоянных доработок это иногда происходит ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 14.05.2002, 09:33:06 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
Приведите пример процедуры, с которой возникают эти казусы... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.05.2002, 15:53:15 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
На счет второго вопроса: Если уж по другому никак не получается, то можно выкрутиться вот так: DECLARE @rc INT BEGIN TRAN EXEC @rc=sp_executesql N'suspicious SQL statement' IF @rc <> 0 BEGIN -- exception handling here ... ROLLBACK TRAN END ELSE BEGIN COMMIT TRAN END PRINT @@TRANCOUNT Правда ошибки с Severity Levels 20 и выше приводят к закрытию текущей сессии. В этом случае вышеприведенный метод не работает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.05.2002, 13:31:07 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
Если я не ошибаюсь, то MSSQL проверяет число открытых транзакций до и после выполнения процедуры. create proc My_proc2 AS BEGIN TRAN exec My_proc2 Так что ругать ся должно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 05:52:52 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
Пример-то как раз привести не могу - на какой именно процедуре это происходит установить невозможно - пользователь продолжает нормально работать и даже не догадывается о том, что какая-то там транзакция "повисла" - а я замечаю "зависание" транзакции слишком поздно, когда мне сообщают о блокировках, - за это время люди успевают по сотне-полторы раз обратиться к серверу. Я пока борюсь с этим ручками - мониторю счетчик "Active tranzactions" - и как только замечаю достаточно продолжительную - sp_who затем Kill. Отключение одного процесса помогает в 90 % случаев, иногда приходится убить 2-3 коннекшина. Опрос отключенных юзеров ничего не дал - все они работают в совершенно разных отделах и выполняют разные функции - это значит, что быстрее всего я чего-то глобально не понимаю и делаю одинаковую принципиальную ошибку во многих местах. Могу привести пример стандартного оформления транзакций во всех sp: BEGIN TRAN INSERT INTO tbl_2_Goods (GoodsNameID, Cost, StockPlaceID) VALUES (@GoodsNameID, 0, @StockPlaceID) SET @GoodsID = @@Identity IF @@Error<>0 BEGIN ROLLBACK TRAN RAISERROR 13091'Операция отменена!' RETURN END SELECT @StockIDTo = StockID FROM dbo.tbl_2_LogisticOrders WHERE (LogisticOrderID = @LogisticOrderID) IF @StockIDTo IS NULL BEGIN ROLLBACK TRAN RAISERROR 13092'Не задан склад контракта! Операция отменена!' RETURN END INSERT INTO tbl_2_LogisticOrderGoods(LogisticOrderID, GoodsID, OrderedQuantity, DeliveredQuantity, IncompliteQuantity) VALUES (@LogisticOrderID, @GoodsID, 0, 0, @IncompliteQuantity) IF @@Error<>0 BEGIN ROLLBACK TRAN RAISERROR 13091'Операция отменена!' RETURN END COMMIT TRAN RETURN Подобным образом транзакции оформлены везде... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 06:59:29 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
>ли я не ошибаюсь, то MSSQL проверяет число открытых транзакций до и после выполнения процедуры. >create proc My_proc2 AS BEGIN TRAN >exec My_proc2 > >Так что ругать ся должно. Такая ситуация нормально обрабатывается клиентским приложением, и никаких проблем не возникает. Но в моем случае никакого ругательства не происходит - пользователь без проблем продолжает работать. Пример - добавление товаров в заказ: были случаи, кода пользователь добавил 20 позиций, после чего я его отрубил - после перезапуска клиентского приложения в заказе осталось 12 позиций. И это при том, что добавление позиций происходит так: двойной клик мышки по справочнику, вызов sp добавления, следующий двойной клик. Процедуру добавления позиции в заказ облазил вдоль и впоперек - все нормально, причем эту-же процедуру вызывает еще 60 человек в пяти офисах по сотне раз в день... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 07:13:33 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
Я, конечно, не уверен, но то, что бросается в глаза: 1. Проверять код ошибки необходимо СРАЗУ за подозрительной командой, т.е. код должен быть примерно таким: DECLARE @SaveError Int SET @SaveError=0 INSERT ... SET @SaveError=@@ERROR ... IF @SaveError<>0 ... ELSE ... Ты же вставил после команды INSERT команду присвоения SET, которая разумеется завершилась без ошибок и после ее выполнения системная переменная @@ERROR благополучно приняла значение 0 2. Не делай несколько точек выхода из процедуры (несколько RETURN). За ними очень трудно проследить и это место потенциальных ошибок. Делай безусловный переход по меткам (GOTO) Примерный код: DECLARE @SaveError Int SET @SaveError=0 BEGIN TRANSACTION ... INSERT ... SET @SaveError=@@ERROR ... IF @SaveError<>0 GOTO StopTran ... StopTran: IF @@TranCount>0 IF @SaveError=0 COMMIT TRANSACTION ELSE ROLLBACK TRANSACTION RETURN ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 07:17:10 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
А может, клиент не завершает транзакцию соединения? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 07:52:18 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
по поводу нескольких точек выхода из программы- тут я почти согласен, но такой уж стиль у меня выработался, плюс терпеть не могу GOTO. >1. Проверять код ошибки необходимо СРАЗУ за подозрительной командой, т.е. код должен быть примерно таким: спасибо за новую мысль - попробую. Но насколько я понимаю, весли я выйду из sp и при этом перед выходом останется открытая транзакция, то сервер должен ругнуться на это и транзакцию прибить(всегда ли это так?)... но ничего такого не происходит - транзакция остается открытой... Мистика какая-то, причем ситуация не изменилась при переходе с v70_sp2->v70_sp3->v70_sp4->v2k_sp2 >RE: Deem >А может, клиент не завершает транзакцию соединения? к счастью, на клиенте нет ни одной команды кроме как открытие коннекшина и ADODB.Command.Execute. Нет ни одного асинхронного запроса - только синхронный режим. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 13:08:30 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
Вообще-то, насколько я понимаю, если не была дана специальная команда, то транзакция будет жить все время существования текущего соединения. При закрытии соединения все открытые транзакции автоматически откатываются (ROLLBACK). И я не вижу тут причины для сообщения об ошибке. Посмотри еще текущую настройку SET IMPLICIT_TRANSACTION. По умолчанию она в OFF. Если она выставлена в ON, то у тебя будут автоматически открываться транзакции при выполненнии некоторых команд. А вот автоматически закрываться не будут. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 13:39:03 |
|
||
|
"Зависание" транзакции
|
|||
|---|---|---|---|
|
#18+
> Вообще-то, насколько я понимаю, если не была дана специальная команда, то транзакция будет жить все время > существования текущего соединения. При закрытии соединения все открытые транзакции автоматически откатываются > (ROLLBACK). И я не вижу тут причины для сообщения об ошибке. транзакция жить-то будет, но клиенту будет возвращено сообщение об ошибке, типа количество открытых транзакций до входа в процедуру и после выхода не одинаковое. Вот тестовый пример: Begin Tran Insert Into tbl_TestTran (mName) Select LEFT(mName,50) From tbl_GoodsNAmes и если в приложении эту ошибку перехватить и спрятать типа On Error Resume Next, то эта транзакция так и останется! Похоже, проблема в клиентском приложении - иногда ошибка почему-то не перехватывается, но это уже дело техники и обсуждения не стоит. Спасибо кто навел на нужные мысли. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.05.2002, 14:54:22 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32030755&tid=1822660]: |
0ms |
get settings: |
5ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
48ms |
get topic data: |
7ms |
get forum data: |
2ms |
get page messages: |
31ms |
get tp. blocked users: |
1ms |
| others: | 191ms |
| total: | 299ms |

| 0 / 0 |
