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

Откуда:
Сообщений: 157
Добрый день.

В веб аппликации выполняется редактирование объекта "задание", что-то в роде Мантиса/Джиры. В моменте сохранения изменений по стороне базы данных идет вызов нескольких процедур, запись основных данных (плоские) и связных (комментарии, доп. поля и т.п). В каждой из процедур в зависимости от логики принимается решение о добавлении кусочка текста к большому письму. Эти кусочки собираются и в конце отсылается один mail. Собственно проблема со сбором этих кусочков, ни контекст ни временные таблицы не помогают т.к. вэб приложений использует "connection pooling" и перед каждым вызовом процедуры вызывается системная процедура sp_reset_connection которая чистит все временное. Логически выглядит так:
1. begin transaction
2. open connection -> sp_reset_connection -> my_proc_1
2. open connection -> sp_reset_connection -> my_proc_2
..
10. open connection -> sp_reset_connection -> my_proc_10
11. commit transaction

Как в таком случае можно на уровне сессии иметь что-то общее для процедур? Может быть постоянная таблица, но не могу придумать что будет уникальным ключом, чтоб процедуры могли достучаться до своей записи.
Еще одна проблем что вынужден действовать без изменения вэб приложения, т.е. не могу дописать OUT параметр который будет раздавать что-то процедурам в цепочке.
26 июл 16, 10:13    [19455206]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31439
mezzanine
Логически выглядит так:
1. begin transaction
2. open connection -> sp_reset_connection -> my_proc_1
2. open connection -> sp_reset_connection -> my_proc_2
..
10. open connection -> sp_reset_connection -> my_proc_10
11. commit transaction
Вообще в таком случае и транзакция будет откатываться.

Стратегически правильное решение - управлять коннектами так, как нужно для реализации логики работы приложения.
Т.е. если нужно для некоего единого процесса обработки иметь общие данные, общую транзакцию и т.п., то и нужно делать это в одном коннекте, а не в разных.
Или альтернатива - эмулировать один коннект программно, наворачивая для этого кучу кода. Ключом можно сделать некий ИД запуска приложения, например.
26 июл 16, 11:09    [19455570]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

Откуда:
Сообщений: 157
С транзакцией все хорошо. Действительно одна, в случае ошибки например на 5 процедуре откатывается все целиком, ну и коммитится тоже. Как мне объяснили программисты WWW что это стандартное поведение ADO.NET при пуле соединений и управлять им особо не получится.
26 июл 16, 12:18    [19456098]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

Откуда:
Сообщений: 157
What does sp_reset_connection do?
26 июл 16, 12:22    [19456135]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
invm
Member

Откуда: Москва
Сообщений: 9406
mezzanine
С транзакцией все хорошо.
Думаете? Узнайте у архитектора этого чуда - зачем нужны распределенные транзакции, если все действия в них локальны?
mezzanine
Как в таком случае можно на уровне сессии иметь что-то общее для процедур?
Т.к. транзакция распределенная, можно найти ее идентификатор:
select
 at.transaction_uow
from
 sys.dm_tran_current_transaction ct join
 sys.dm_tran_active_transactions at on at.transaction_id = ct.transaction_id;
26 июл 16, 12:45    [19456322]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

Откуда:
Сообщений: 157
Все процедуры выполняются в рамках одной транзакции. Стартует ее веб приложение и в зависимости от галочек на форме, действий пользователя меняется количество вызываемых процедур. Выглядит логически вполне нормально. Вместо одной процедуры с 100 параметрами и сложной логикой. База предоставляет интерфейсы, вэб ими пользуются.
26 июл 16, 12:50    [19456373]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
aleks2
Guest
mezzanine
Выглядит логически вполне нормально.


Но вызывает стойкий геморрой.
26 июл 16, 13:04    [19456471]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

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

А этот UOW будет уникальный всегда? Или может временами повторяться.
26 июл 16, 13:44    [19456832]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

Откуда:
Сообщений: 157
Что может быть уникальным ключом UID для постоянной таблицы вида:
CREATE TABLE dbo.ctx_connection_attr (
  uid NVARCHAR(4000) NOT NULL,
  attr_name NVARCHAR(100) NOT NULL,
  attr_value NVARCHAR(4000) NULL,
)

Чтобы можно было в ситуации использования connection pooling и вызова N процедур в одной транзакции получать значения атрибутов. Идентификатор транзакции transaction_uow в моем случае пустой, transaction_id повторяется по рестарту сервера.
4 авг 16, 14:09    [19498917]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2322
mezzanine
Что может быть уникальным ключом UID для постоянной таблицы вида:
IDENTITY, NEWID(), NEWSEQUENTIALID()

mezzanine
transaction_id повторяется по рестарту сервера.
И что? После того как транзакция закончилась можно эти данные смело удалять ибо они станут "сиротками".

mezzanine
Еще одна проблем что вынужден действовать без изменения вэб приложения
Ваша основная и единственная проблема в том что вы пытаетесь прикрутить функционал, который не предусмотрен архитектурой системы.
4 авг 16, 20:33    [19501709]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
mezzanine
Member

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

В курсе о таких типах. Тут проблема в том что в одной транзакци выполняется пачка процедур. Еще раз покажу на пальцах:

1. ADO -> begin transaction
2. ADO -> open connection -> sp_reset_connection (ЧИСТИТ ВСЕ context, tem_table ...) -> my_proc_1
3. ADO -> open connection -> sp_reset_connection (ЧИСТИТ ВСЕ context, tem_table ...) -> my_proc_2
..
10. ADO -> open connection -> sp_reset_connection (ЧИСТИТ ВСЕ context, tem_table ...) -> my_proc_10
11. ADO -> commit transaction

На шаге 2 в my_proc_1 выполняеися что-то абстрактное, и больше не должно выполниться в последующих процедурах my_proc_(N). Хотя может выполнятся на любом шаге, главное чтоб в следующих не было.
Предложеные Вами ключи не подходят т.к. my_proc_2 ... my_proc_(N) никак не узнают значения ключа чтоб получить уникальную строку.
Глобальные таблицы выживают при вызове sp_reset_connection но не вижу большой пользы по сравнению с обычной. Поэтому создал выше приведенную таблицу и генерирую ключ как [Connection GUID] + [Transaction ID]:
CREATE FUNCTION dbo.f_ctx_context_key ()
RETURNS NVARCHAR(100)
AS
BEGIN
  DECLARE @result NVARCHAR(100) = NULL,
          @connection_id UNIQUEIDENTIFIER,
          @transaction_id BIGINT;

  SELECT @connection_id = dec.connection_id
    FROM sys.dm_exec_connections dec
    WHERE session_id = @@spid;

  SELECT @transaction_id = dtct.transaction_id
    FROM sys.dm_tran_current_transaction dtct;

  SET @result = (CAST(@connection_id AS NVARCHAR(36)) + '|' + CAST(@transaction_id AS NVARCHAR(19)))

  RETURN @result;
END;

Этот ключ будет всегда уникальным на уровне транзакци и не страшны reset коннектов.

До 2005 верси сервер не ресетовал контекст и все было отлично. Разработчик сам решал чистить данные или работать с ними дальше. А тут решили обрубить. А писать монструальные процедуры all-in-one рука не подымается. Код должен быть повторно используемый.
4 авг 16, 20:58    [19501800]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31439
mezzanine
До 2005 верси сервер не ресетовал контекст и все было отлично. Разработчик сам решал чистить данные или работать с ними дальше.
Ресет коннекта делает клиент, при чём тут сервер?
4 авг 16, 22:10    [19502083]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
leov
Member

Откуда: С-Петербург
Сообщений: 616
mezzanine
What does sp_reset_connection do?
а оно вообще работает?
там вроде написано It will abort open transactions
4 авг 16, 23:40    [19502450]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
Владислав Колосов
Member

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

а Вы что - используете временную таблицу для накопления результата? Не видите противоречия? Данные собираете на сервере, а управляете последовательностью вызова с клиента? Так и собирайте данные на клиенте или отдайте управление серверу.
5 авг 16, 11:29    [19504287]     Ответить | Цитировать Сообщить модератору
 Re: Общий кэш процедур в одной транзакции при connection pooling  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7868
Пул вообще прикольная штука - клиент-то может отключиться, но выполнение продолжается на сервере. Для полной остановки надо и отключиться и очистить пул.
5 авг 16, 11:31    [19504302]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить