powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
7 сообщений из 7, страница 1 из 1
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021079
MishGan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Имеем проблему:
Есть приложение, работающее с MSSQL Server 7/2000 через ADO. При работе выполнялись запросы, с установленным параметром CursorLocation=adUseClient. И все было нормально..
Пока не решили переделать приложение, чтобы запросы выполнялись параметром CursorLocation=adUseServer. И обнаружилась интересная фича: если в какой-то момент времени есть открытый серверный курсор, то при попытке вызвать хранимую процедуру (SP) ADO создает дополнительную сессию. В этой сессии выполняется SP, после чего сессия закрывается. И все бы хорошо, да и почти не заметно для неискушенного, но есть 2 проблемы в связи с этим:
1) Во многих хранимых процедурах используется идентификатор текущей сессии (@@SPID), например для определения того, заблокирован объект или нет и т.д.
2) Если используется Application role, то в новой сессии она не активизируется и у пользователя отсутствую права на выполнение SP.
Переделывать логику приложения в связи с этой особенностью ADO не хочется. Посему вопрос: может кто с этим сталкивался и знает как эту фичу отключить или как с ней правильно бороться.

Для того чтобы наглядно представить проблему привожу тестовый пример, иллюстрирующий особенность проблемы.

1) На сервере создаем две таблицы и одну SP. При вызове SP в эти таблицы пишется идентификатор сессии в рамках которой была вызвана процедура

create table t1 ("ID" INT)
go

select * into t2 from master..sysprocesses where 1=2
go

create procedure p1 as
begin
insert into t1 values (@@SPID)
insert into t2 select * from master..sysprocesses where spid=@@SPID
end;
go

2) Далее из клиенского приложения выплняем примерно такой код:

ADOConnection = CreateObject("ADODB.Connection");
ADOConnection.ConnectionString="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=landocs2000;Data Source=MICHAIL\MSSQL2000;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID=MICHAIL;Use Encryption for Data=False;Tag with column collation when possible=False";
ADOConnection.CursorLocation = 2; //adUseServer
ADOConnection.ConnectionTimeOut = 600;
ADOConnection.CommandTimeOut = 600;
ADOConnection.IsolationLevel = 4096; //adXactReadCommitted
ADOConnection.Mode = 0; //adModeUnknown
ADOConnection.Open();

ADOCmd0 = CreateObject("ADODB.Command");
ADOCmd0.ActiveConnection = ADOConnection;
ADOCmd0.CommandTimeout = 600;
ADOCmd0.CommandText="p1";
ADOCmd0.CommandType=4; //adCmdStoredProc
ADOCmd0.Execute();

ADOCmd1 = CreateObject("ADODB.Command");
ADOCmd1.ActiveConnection = ADOConnection;
ADOCmd1.CommandTimeout = 600;
ADOCmd1.CommandText="SELECT * FROM sysobjects";
Rs1 = ADOCmd1.Execute();

ADOCmd2 = CreateObject("ADODB.Command");
ADOCmd2.ActiveConnection = ADOConnection;
ADOCmd2.CommandTimeout = 600;
ADOCmd2.CommandText="p1";
ADOCmd2.CommandType=4; //adCmdStoredProc
ADOCmd2.Execute();

Rs1.MoveFirst();
While Rs1.EOF()=0 Do
Message(Rs1.Fields("ID").Value);
Rs1.MoveNext();
EndDo;
Rs1.Close();

ADOCmd3 = CreateObject("ADODB.Command");
ADOCmd3.ActiveConnection = ADOConnection;
ADOCmd3.CommandTimeout = 600;
ADOCmd3.CommandText="p1";
ADOCmd3.CommandType=4; //adCmdStoredProc
ADOCmd3.Execute();


После выполнения этого кода посмотрим, что есть в таблицах t1 и t2
select * from t1
select * from t2
Видим, что идентификаторы сессий разные. Это говорит о том, что процедура, которая вызывалась объектом ADOCmd2, выполнялась в отдельной сессии.
Если CursorLocation изменить на adUseClient - то все OK.
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021130
В общем-то, это всем известно. Что тебя так поразило?
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021134
Mishgan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если это всем известно - уже хорошо. А можно ли где-нибудь про это почитать.
И с этим ка-нибудь можно бороться. Нас так совсем не устраивает и чего делать не знаем.
Спасибо.
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021164
Где прочитать, так с ходу не скажу. Наверно, в MSDN есть.
А суть проста - ADO таким образом обходит ограничение протокола TDS, который не позволяет одновременно фетчить несколько наборов данных в одной сессии. Если бы ADO так не поступало, то при открытии серверного курсора больше ничего невозможно было бы сделать до его закрытия.
Решение тоже на поверхности - не использовать серверные курсоры.
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021173
MishGan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Понятно.
Только вот если использовать провайдер ODBC-шный, то все нормально работает - никаких дополнительных сессий не открывается. Я всегда думал, что в ODBC используется аналог серверного курсора. И как в этом случае обходится ограничение TDS? Или он тут вообще не используется?
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021682
dmitry
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот только что увидел SET CONTEXT_INFO, Associates up to 128 bytes of binary information with the current session or connection. Похоже это выход. Клиентское приложение создает соединение (application role). Оператор вводит логин для работы с базой и этот логин будем указывать в качестве CONTEXT_INFO для каждого соединения со стороны клиента. Тогда всегда cможем узнать хозяина для клиентского процесса. Сейчас буду пробовать.

MSDN: context information for session
...
Рейтинг: 0 / 0
ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
    #32021789
MishGan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2. Dmitry
Интерестно все это, но только вот не понятен такой момент:
Если создается ADO-шная сессия для вызова SP (назовем эту сесси дочерней), то у нее CONTEXT_INFO будет незаполненным и непонятно каким образом узнать SPID сессии, которая ее (дочернюю сессию) породила.
Кроме того, каким образом для этой дочерней сессии делать set_approle тоже непонятно.
Короче мы решили от серверных курсоров отказываться напрочь.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / ADO: CursorLocation=adUseServer. При каждом вызове SP создается новая сессия (+)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]