У меня настроена группа доступности всегда, и я хочу убедиться, что мои пользователи используют ApplicationIntent = ReadOnly в своих строках подключения.
С сервера SQL через DMV (или расширенные события или что-то еще), могу ли я узнать, был ли пользователь, связанный с ApplicationIntent = ReadOnly в своей строке подключения?
Пожалуйста, не отвечайте с тем, как ПРЕДОТВРАТИТЬ соединения - это не тот вопрос, о котором идет речь. Я не могу просто прекратить соединения, потому что у нас есть приложения, которые соединяются без правильной строки, и мне нужно знать, какие из них, поэтому я могу работать с разработчиками и пользователями, чтобы постепенно исправить это с течением времени.
Предположим, что у пользователей есть несколько приложений. Например, Боб соединяется как с SQL Server Management Studio, так и с Excel. Он подключается к SSMS, когда ему нужно сделать обновления, и к Excel, когда ему нужно сделать чтение. Мне нужно убедиться, что он использует ApplicationIntent = ReadOnly, когда он соединяется с Excel. (Это не точный сценарий, но он достаточно близок для иллюстрации.)
источник
sqlserver.read_only_route_complete
как это происходит только на первичном.Ответы:
Подбирая
sqlserver.read_only_route_complete
расширенное событие, упомянутое Kin и Remus, это хорошее событие отладки , но оно не несет с собой много информации - простоroute_port
(например, 1433) иroute_server_name
(например, sqlserver-0.contoso.com) по умолчанию , Это также поможет определить, когда соединение с намерением только для чтения было успешным. Существуетread_only_route_fail
событие , но я не мог получить его в огонь, может быть , если возникла проблема с маршрутизацией URL, он , казалось, не огонь , когда вторичный экземпляр был недоступен / выключения, насколько я мог сказать.Однако я добился некоторого успеха, присоединившись к нему с
sqlserver.login
включенным отслеживанием событий и причинно-следственных связей, а также некоторыми действиями (напримерsqlserver.username
), чтобы сделать его полезным.Действия по воспроизведению
Создайте сеанс расширенных событий для отслеживания соответствующих событий, а также полезных действий и отслеживания причинно-следственных связей:
Запустите сеанс XE (рассмотрите выборку, поскольку это событие Debug) и соберите несколько имен входа:
Обратите внимание, что sqlserver-0 - мой читаемый вторичный сервер, а sqlserver-1 - первичный. Здесь я использую
-K
переключательsqlcmd
для имитации входов в интенты приложения только для чтения и некоторых входов в SQL. Событие readonly запускается при успешном входе в систему только для чтения.Приостановив или остановив сеанс, я могу запросить его и попытаться связать два события, например:
В запросе должны отображаться имена входа с намерением приложения только для чтения и без него:
read_only_route_complete
является событием отладки, поэтому используйте его экономно. Рассмотрим выборку для примера.Я пытался заставить
pair_matching
цель работать, но не хватило времени. Здесь есть некоторый потенциал для развития, что-то вроде:источник
Нет, не похоже, что существует какое-либо свойство соединения, доступное для DMV (в sys.dm_exec_connections или sys.dm_exec_sessions ) или даже CONNECTIONPROPERTY, которое относится к
ApplicationIntent
ключевому слову ConnectionString.Однако, возможно, стоит запросить через Microsoft Connect, чтобы это свойство было добавлено в
sys.dm_exec_connections
DMV, поскольку оно , по-видимому, является свойством соединения, которое хранится где-то в памяти SQL Server, на основе следующей информации, найденной на странице MSDN для: Поддержка SqlClient для высокой доступности, аварийного восстановления (выделено курсивом):Если
USE
утверждение может быть проверено, тоApplicationIntent
после первоначальной попытки подключения он должен существовать. Однако я лично не проверял это поведение.PS Я думал, что мы могли бы использовать факты, которые:
USE
оператора.Идея состояла в том, чтобы создать новую базу данных исключительно с целью тестирования и отслеживания этого параметра. Новая БД будет использоваться в новой группе доступности, для которой будут разрешены только
READ_WRITE
подключения. Теория заключалась в том, что внутри триггера входа в систему,EXEC(N'USE [ReadWriteOnly]; INSERT INTO LogTable...;');
внутриTRY...CATCH
конструкции, в которой по существу ничего нет вCATCH
блоке, либо не возникнет ошибки для соединений ReadWrite (которая будет регистрироваться в новой БД), либоUSE
произойдет ошибка на соединениях ReadOnly, но тогда ничего не произойдет, поскольку ошибка перехватывается и игнорируется (иINSERT
утверждение никогда не будет достигнуто). В любом случае фактическое событие входа в систему не будет предотвращено / запрещено. Код триггера входа в систему будет:К сожалению, при тестировании эффекта выдачи
USE
оператораEXEC()
внутриTRY...CATCH
внутренней части транзакции я обнаружил, что нарушение доступа было прерыванием на уровне пакета, а не прерыванием на уровне оператора. И настройкаXACT_ABORT OFF
ничего не изменила. Я даже создал простую хранимую процедуру SQLCLR для использования,Context Connection = true;
а затем вызвал ееSqlConnection.ChangeDatabase()
внутри,try...catch
и транзакция все еще была прервана. И вы не можете использоватьEnlist=false
в контексте подключения. И использование обычного / внешнего соединения в SQLCLR для выхода за пределы транзакции не поможет, так как это будет совершенно новое соединение.Существует очень, очень тонкая возможность, что HAS_DBACCESS может быть использован вместо
USE
оператора, но у меня действительно нет больших надежд на то, что он сможет включить текущую информацию о подключении в свои проверки. Но у меня нет возможности проверить это тоже.Конечно, если есть флаг трассировки, который может привести к тому, что нарушение доступа не будет прерывать пакет, то упомянутый выше план должен сработать ;-).
источник
ROLLBACK
в триггереINSERT
входа на таблицу регистрации :-)Насколько больным ты хочешь быть? Прокси-поток не так сложно прокси, мы сделали это для нашего приложения SaaS. Бит, который вы ищете (буквально немного), находится в сообщении login7. Ваши пользователи могут подключаться через прокси и регистрировать / применять бит там. Черт, ты можешь даже включить это для них. :)
источник
Использует ли ваше приложение служебную учетную запись или несколько учетных записей? Если это так, используйте расширенное событие для отслеживания трафика входа в систему, но исключите учетные записи служб на основном постоянном сервере. Теперь вы сможете увидеть, кто входит в систему на основном постоянно включенном сервере и не использует строку подключения только для чтения. Я готовлюсь к установке Always-On, и это то, что я собираюсь сделать, если вы не скажете мне, что это не будет работать.
источник
К сожалению, у меня нет среды, чтобы протестировать следующее, и, несомненно, есть несколько моментов, в которых он может потерпеть неудачу, но я выложу его там, чтобы оно того стоило.
Хранимая процедура CLR имеет доступ к текущему соединению через
new SqlConnection("context connection=true")
конструкцию (взято отсюда ). Тип SqlConnection предоставляет свойство ConnectionString . Поскольку ApplicationIntent находится в исходной строке подключения, я предполагаю, что оно будет доступно в этом свойстве и может быть проанализировано. Конечно, в этой цепочке много раздач, так что у всех есть возможность сделать грушевидную форму.Это запустится из триггера входа в систему, и необходимые значения сохранятся по мере необходимости.
источник