Сценарий
Его довольно сложно объяснить, но у меня есть процедура, которая обновляет данные в двух базах данных на instance1, и как часть процесса (это курсор по соответствующим причинам) ему необходимо обновлять базу данных на instance2, где выполняются определенные критерии. Если строка кода, которая ссылается на instance2, изменена на локальный экземпляр, процедура выполняется менее чем за минуту. Если он настроен для ссылки на правильное местоположение в экземпляре 2, процедура занимает 30-40 секунд на запись (мы никогда не позволяли ей завершаться).
История (этим утром)
При проверке предполагаемого плана выполнения код, который выполняет обновление отдельной записи в экземпляре 2, использует удаленное сканирование таблицы, содержащей 100 тыс. Записей.
Я изменил это с
Update C set col1 = @val1, col2 = @val2 where col2 = @ID
к
Execute ('Update C set col1 = @val1, col2 = @val2 where col2 = @ID') as user1 at Instance2
где Instance2 - это связанный сервер, а user1 - это имя для входа в sql, для которого на связанном сервере включена функция олицетворения. Это было сделано для того, чтобы процесс обновления мог использовать кластерный индекс на col2 и, следовательно, избежать сканирования таблицы.
Проблема
Теперь мы получаем ошибки безопасности / аутентификации, и скрипт не работает с
Msg 15274, уровень 16, состояние 1, процедура "procname", строка 263
Доступ к удаленному серверу запрещен, поскольку текущий контекст безопасности не является доверенным.
Может ли кто-нибудь посоветовать мне, что мне нужно настроить, чтобы разрешить выполнение этого обновления? Или есть лучший способ получить обновление для использования индекса в таблице в Instance2? Из моей таблицы знаний подсказки не разрешены для удаленных запросов ...?
Большое спасибо
Джонатан
Для меня выделялись две основные проблемы:
Ваш оператор execute отправляет буквальные строки (например, '@ val1') внутри запроса в Instance2, потому что все они содержатся внутри строки. Чтобы отправить значения, вам нужно будет изменить эту часть оператора execute, чтобы он читался:
Execute ('Update C set col1 = ' + @val1 + ', col2 = ' + @val2
+ ' where col2 = ' + @ID) as user1 at Instance2
Обратите внимание, что в приведенном выше коде предполагается, что и @ val1, и @ val2 являются типами, которые не должны заключаться в кавычки, иначе вы бы использовали следующее:
Execute ('Update C set col1 = ''' + @val1 + ''', col2 = ''' + @val2
+ ''' where col2 = ''' + @ID + ''') as user1 at Instance2
Для вашего запроса не используется какая-либо потенциальная предварительная оптимизация на Instance2. Поэтому я бы предложил создать хранимую процедуру на Instance2, чтобы вы могли извлечь выгоду из оптимизации запроса до выполнения, а также использовать все подсказки по оптимизации, которые вы, возможно, захотите поместить в запрос. Итак, в Instance2 вы можете создать такую процедуру (еще раз обратите внимание, что я принял целочисленные типы данных):
CREATE PROCEDURE user1.UpdateC (@val1 int, @val2 int, @ID int) AS
BEGIN
UPDATE C WITH (ROWLOCK) SET col1 = @val1, col2 = @val2 WHERE col2 = @ID
END
Затем ваш локальный сценарий может заменить исправленный код из части 1 выше следующим (снова, предполагая целые числа):
EXECUTE ('EXECUTE user1.UpdateC ' + @val1 + ', ' + @val2 + ', ' + @ID)
AS user1 AT Instance2
MSDN по безопасности связанного сервера: http://msdn.microsoft.com/en-us/library/ms175537.aspx
Настройка связанных серверов для делегирования: http://msdn.microsoft.com/en-us/library/ms189580.aspx
Аналогичная проблема с вашей (я считаю): http://dbaspot.com/forums/ms-sqlserver/173869-access-remote-server-denied-because-current-security-context-not-trusted-sqlstate-42000-error-15274-a-2.html
другое решение на SQL Server Central: http://www.sqlservercentral.com/Forums/Topic476794-149-1.aspx