Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Валентин дядька
Member

Откуда:
Сообщений: 14
Всем доброго времени!

Есть такая ситуевина:
2 сервера А и Б прилинкованные друг к другу да ещё и loopback оба (физически на разных машинах).Есть приложение, которое добавляет сначала в таблицу базы расположенной на сервере А.На таблице прописан триггер (after update insert), который добавляет по условию в таблицу на сервер Б.[b]На сервере Б, на этой таблице так же висит триггер, который из приложения обновляет таблицу А и что-то вытягивает для чего-то из таблицы на сервере Б далее в триггере(обычный select).Так вот бывает такое, что у некоторых пользователей(не у всех, но изредка случается), при попытке обновить таблицу из сервера Б таблицу на сервере А(ту на которой триггер пишет в таблицу А выделено жирным выше) зависает приложение и выкидывает ошибку Transaction context in use by another session

Подскажите плз, что в таких ситуациях можно попробовать сделать? про распределенные транзакции на loopback серверах слышал, но соль в том, что ошибка возникает далеко не всегда.

Спасибо!
6 ноя 17, 01:07    [20929378]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Валентин дядька
Всем доброго времени!

Есть такая ситуевина:
2 сервера А и Б прилинкованные друг к другу да ещё и loopback оба (физически на разных машинах).Есть приложение, которое добавляет сначала в таблицу базы расположенной на сервере А.На таблице прописан триггер (after update insert), который добавляет по условию в таблицу на сервер Б.[b]На сервере Б, на этой таблице так же висит триггер, который из приложения обновляет таблицу А и что-то вытягивает для чего-то из таблицы на сервере Б далее в триггере(обычный select).Так вот бывает такое, что у некоторых пользователей(не у всех, но изредка случается), при попытке обновить таблицу из сервера Б таблицу на сервере А(ту на которой триггер пишет в таблицу А выделено жирным выше) зависает приложение и выкидывает ошибку Transaction context in use by another session

Подскажите плз, что в таких ситуациях можно попробовать сделать? про распределенные транзакции на loopback серверах слышал, но соль в том, что ошибка возникает далеко не всегда.

Спасибо!

Смотрите, в чем цимес - у Вас одна база обновляет вторую, а вторая первую. А где точка правды? Какая база важнее? В случае отказа базы и рестора на резервную копию - для какой базы это будет совсем плохо, а для какой не очень?
То есть я бы начал с того, что определил - в каждый конкретный момент времени какая-то информация, которая находится в одной из баз и которую может обновить что-то из другой базы, она чем управляется - приложением, которое явно работает с этой базой, или действием триггера, который из другой базы что-то делает.
6 ноя 17, 01:13    [20929383]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Валентин дядька,
Поясню момент. Вот есть таблица баланса на базе A и таблица операций по карте клиента на базе B. Может быть, архитектуру переделать? Потому что операции в B шли плюс 10 рублей, плюс 10 рублей, минус 5 рублей, триггерами записался баланс 15. Потом раз - и база B разрушена, откатились на состояние, где есть операция плюс 10 рублей. А баланс то в базе B остался как 15 рублей. Надеюсь, упрощенная картина достаточно наглядная?
6 ноя 17, 01:16    [20929388]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Andy_OLAP,

То есть баланс в базе A остался. 15 рублей. А в базе B после рестора осталась только первая проводка из трех. Мы получили 2 версии правды. Баланс 15 рублей - правда. Баланс 10 рублей - тоже правда. А далее в базе B еще поступит 10 рублей, и там при пересчете Вы получите 20, а баланс в базе A для приложения, которое с этой базой работает, покажет 25 рублей.
Я бы считал триггеры пистолетом, из которого стреляют себе в ногу. Увы.
6 ноя 17, 01:20    [20929390]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Валентин дядька
Member

Откуда:
Сообщений: 14
Andy_OLAP,
Насколько я Вас понял, вы имеете ввиду, что надо переделать код так, чтобы минимизировать потерю нужной информации.
Но я оборачивал участки кода, которые, как мне казалось наиболее подходящие кандидаты на эту ошибку процедурой, которая пишет время работы участка кода и соответственно, когда у нас будет только одна метка, то можно будет собрать некоторую статистику и выявлять закономерность, но апдейт записи из приложения в таблице на сервере Б,которая добавляется из триггера первого сервера, после зависания приложения полностью откатывает транзакцию и т.о. ничего не пишется в логи о времени работы кода.Значит надо оборачивать сам апдейт в приложении, но это менее информативным получится. Есть у вас предположения?
6 ноя 17, 01:39    [20929396]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Валентин дядька,

Я понял Вашу проблему, но тут нужно смотреть на код и долго думать. Получается - есть опорная таблица в базе A, там создается запись, далее она частично прилетает в базе B триггером, затем приложение обновляет именно в базе B.
Ну и возвращаясь к примеру с балансом клиента. Упростим его.

Есть инкрементальный id int identity(1,1), добавляем Иванова - он становится 101, потому что 100 записей уже есть.
В базу B прилетает id 101, фамилия Иванов и начальный баланс 100 рублей.
Приложение начисляет ему выигрыш 5 рублей, баланс становится 115. Причем через приложение это сделал конкретный пользователь, он уверен, что у Иванова 115 рублей.
Далее идет сбой в базе A и откат на состояние, когда Иванова нет. Ну что поделаешь. Приложение, которое работает с базой A, добавляет Петрова и посылает на B. Далее приложение на B базе ставит Петрову выигрыш 1 рубль, баланс нужно установить в 101 рубль (Петров ничего еще не выиграл, а первый выигрыш - это стартовые 100 плюс 1 рубль), но в базе B есть цифра 115. Как это пользователь выиграл, нужно ставить больше, а получается 101 вместо 115. Караул. И внутренняя логика приложения выдает на экран пользователю - не могу Петрову выигрыш записать, у него уже 115.
Зовут того, кто Иванову выигрыш записывал, и говорят "не пойму, что с системой, пытаюсь Петрову id 101 записать выигрыш - и никак", а пользователь удивленно "как это Петров, id 101 это Иванов". А Иванова физически уже нет в базах - ни ФИО, ни адреса, ни почты.
Понимаете расклад? Даже без двойных апдейтов и loopback - вот как обрабатывать такие ошибки? Поэтому я против триггеров. И все транзакции нужно отыгрывать внутри одной базы. Чтобы они легли в один журнал, между 2 чекпойнтами.
6 ноя 17, 01:56    [20929402]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Валентин дядька
надо переделать код так, чтобы минимизировать потерю нужной информации.

Не так. Я не видел Ваш код и не вижу картины в целом. Но если включить интуицию, то Вам нужно не минимизировать потерю, а исключить появление ДВУХ противоречащих друг другу версий нужной информации. Потому что Вы тогда не сможете сказать - вот тут правда, а вот тут мы просто откатились в базе и все потеряли, что нужно.
6 ноя 17, 02:06    [20929411]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Валентин дядька
Member

Откуда:
Сообщений: 14
Andy_OLAP,

Код к сожалению я не могу выложить, так как дома его нет)

Сейчас попробую схематично описать, что происходит в архитектуре:

Приложение добавления в таблицу на сервере A

Пользователь добавляет запись;

Срабатывает триггер(after insert, update)

Для инсерта
Смотрит, есть ли в таблице на сервере Б запись с таким идентификатором:
Если есть, то ничего
если нет, то добавить запись в табл. Б

конец проверки

Смотрит, если прилетел апдейт определенного поля из триггера таблицы на сервере Б, то
обновляет определенное поле текущей(условно, потому-что её обновление запустило триггер) записи таблицы на сервере Б

переходим на сторону Б
-------------------------------------------------------------------------------------------
Cторона Б.

Далее, после этого, приложение на стороне Б "узнаёт"
о добавленной записи и просит её обновить.
Пользователь вводит инфу и нажимает на кнопку по событию которой происходит апдейт.
Тут 2 варианта: либо всё нормально отрабатывает, либо приложение, после нажатия зависает
и выкидывает такую ошибку "Transaction context in use by another session" и откатывает попытку апдейта, ну а триггер на ней уже описал выше (триггер после обновления).
6 ноя 17, 02:45    [20929422]     Ответить | Цитировать Сообщить модератору
 Re: SQL SERVER 2008 sp4 Transaction context in use by another session  [new]
Andy_OLAP
Member

Откуда: я знаю, что Хапоэль Беэр-Шева - чемпион
Сообщений: 3151
Валентин дядька
Приложение добавления в таблицу на сервере A
Пользователь добавляет запись;
....
Далее, после этого, приложение на стороне Б "узнаёт"
о добавленной записи и просит её обновить.
Пользователь вводит инфу и нажимает на кнопку по событию которой происходит апдейт.

Я так и думал - у Вас логика работы в одном приложении разнесено на 2 базы. Перечитайте мой пример с проводками и балансом клиента выше. Как Вы думаете, если ВЫ подобную логику используете - это хорошо или плохо.
Не понял, как приложение на стороне Б "узнает". И что вкладывает во фразу "на стороне Б".

Еще раз вернемся к проводкам и балансу. Завели проводку через приложение в базу A, далее посчитанный баланс (было 10 рублей, стало 20 рублей) прилетел в базу Б, там нет проводок, а есть таблица текущего баланса.
Далее приложение "узнает", что можно работать с балансом пользователя. В базе Б. Смотрит - 20 рублей выше граничных 18 рублей и ставит тип "хороший баланс" (вместо дефолтного "плохого"). В базу Б, правильно?
А далее база A ломается, проводка 10 рублей исчезает, остается только исходные 10 рублей в базе A. И таблицы в базе Б, где в одном месте 18, в другом "хороший".
Ну и....Две версии правды. Как прогнать заново всё после рестора базы А, НЕ через приложение, НЕ через триггеры - у Вас прописано где-то?

Или у Вас в базе Б условно только небольшой кэш, чтобы тип "хороший баланс" потом записать из базы Б в базу А. То есть база Б оперативный расчет, а база А вечное хранение. Но смысл тогда в базе Б - у Вас географически разнесенная база по филиалам и нужно как-то работать? Так не опирайтесь на триггеры, а используйте репликацию, еще что-нибудь - как бы это выразить - наглядное и контролируемое вне зависимости от того, нажал кнопку пользователь в приложении или нет.
6 ноя 17, 12:34    [20929742]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить