вторник, 24 февраля 2009 г.

Использование и настройка псевдонимов (server alias)

Сегодня почти весь день (с перерывами на работу) пришлось заниматься "разруливанием проблем" с приложением на стороне заказчика. Один из сервисов все никак не хотел подключаться к SQL Server-у. Проблема усугублялась тем, что у нашей команды нет доступа к целевому окружению (вообще никакого доступа). Есть доступ только к индусам, которые в свою очередь имеют доступ к этому самому окружению. Причем "интерфейс" к индусам - электронная почта и Skype. После многочисленных советов "разобраться в конфигурации" и столь же многочисленных ответов "все точно так же, как и на стэйджинге", причина таки нашлась: на "проблемном" сервере не был сконфигурирован псевдоним (alias).

Мне сразу по приходу в этот проект не понравилось использование этой "фичи" - и вот опасения материализовались (правда это первый раз когда все было так серьезно). Не могу не признать, что в определенной степени alias - это удобно. Он, например, дает свободу в выборе сервера: можно переключиться с "общественного" на локальный меняя не строку подключения, а настройки псевдонима - т.е. действуя снаружи приложения. Причем псевдоним действует в рамках комьютера, т.е. (потенциально) можно влиять сразу на целый пакет приложений и сервисов. Побочный эффект: пока не посмотришь в настройки - не узнаешь куда же приложение "ходит" за данными. В целом я бы, наверное, избегал использования этой возможности.

Возник, однако, другой вопрос. В случае, когда на компьютере установлен SQL Server Client Tools (на машине разработчика есть с вероятностью 99%) все просто: запускаем SQL Server Configuration Manager, идем в раздел SQL Native Client Configuration, далее Aliases. А если этого пакета нет (на сервере - не редкость)? Как быть? Вариантов несколько:

  • "для слабаков": установить SQL Server Client Tools и получить SQL Server Configuration Manager
  • "для простых админов": в комплекте с клиентскими библиотеками SQL Server идет утилита cliconfg.exe (находится в папке Windows\systems32 так что можно вызывать из командной строки), в которой можно сконфигурировать не только псевдоним, но и много чего еще
  • "для хардкорных админов": воспользоваться Power Shell и SMO (используя объект Microsoft.SqlServer.Management.Smo.Wmi.ServerAlias) - правда для этого придется установить на компьютер PowerShell (в Server 2008 и новее есть всегда) и собственно SMO

Рекомендуемый вариант - "для админов". Или "для хардкорных админов" (возможно с вариациями) - если нужно чтобы настройка происходила автоматически и/или была повторяемой.

За деталями отсылаю к MSDN и документации по PowerShell. А еще рекомендую блог SQL Protocols - такой подробной информации о протоколах SQL Server и решении проблем с соединением вы больше нигде не найдете.

HTH

понедельник, 9 февраля 2009 г.

Об опциях соединения вообще и об IDENTITY_INSERT в частности

Сегодня пришлось "играться" с IDENTITY_INSERT. С удивлением обнаружил прочувствовал что это таки "установка уровня соединения". Не скажу, что это прямо так удивительно, в MSDN об этом явно сказано:

At any time, only one table in a session can have the IDENTITY_INSERT property set to ON. If a table already has this property set to ON, and a SET IDENTITY_INSERT ON statement is issued for another table, SQL Server 2000/2005/2008 returns an error message that states SET IDENTITY_INSERT is already ON and reports the table it is set ON for.

но как-то до сих пор я не особенно обращал внимание на это примечание.

Ну да ладно. Сама ситуация в очередной раз напомнила мне о том, что опции соединения - это вам не просто так и что за ними нужно следить. Главная проблема (с точки зрения программиста) с ними заключается даже не в том, как они инициализируются (это отдельная непростая тема), а в том, что они не сбрасываются при закритии соединения (точнее: при возвращении соединения в пул).

Для того, чтобы постигнуть "всю глубину наших глубин", рассмотрим такой сценарий. Мы выполняем некоторый SQL код и хотим повысить уровень его изоляции:

using(SqlConnection = new SqlConnection())

{

con.Open();

SqlCOmmand com = new SqlCommand("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -- очень важный SQL код", con);

com.ExecuteNonQuery();

}

отлично. Все вроде бы довольны. Кроме того несчастного, которому в очередной раз попадется из пула именно это соединение с уровнем изоляции ... SERIALIZABLE. Для выполнения монстроидального запроса, объединяющего три-четыре-пять не самых маленьких таблиц. Приплыли ... ловить ошибки, возникающие в результате такого неосторожного обращения с опциями соединения, можно ооооочень долго.

Граждане! Будьте бдительны применяя опции соединения (особенно уровень изоляции).

HTH