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
) 유용한 작업을 수행 하는 데 성공했습니다.
재현 단계
확장 이벤트 세션을 작성하여 관련 이벤트와 유용한 조치 및 인과 관계를 추적하십시오.
CREATE EVENT SESSION [xe_watchLoginIntent] ON SERVER
ADD EVENT sqlserver.login
( ACTION ( sqlserver.username ) ),
ADD EVENT sqlserver.read_only_route_complete
( ACTION (
sqlserver.client_app_name,
sqlserver.client_connection_id,
sqlserver.client_hostname,
sqlserver.client_pid,
sqlserver.context_info,
sqlserver.database_id,
sqlserver.database_name,
sqlserver.username
) ),
ADD EVENT sqlserver.read_only_route_fail
( ACTION (
sqlserver.client_app_name,
sqlserver.client_connection_id,
sqlserver.client_hostname,
sqlserver.client_pid,
sqlserver.context_info,
sqlserver.database_id,
sqlserver.database_name,
sqlserver.username
) )
ADD TARGET package0.event_file( SET filename = N'xe_watchLoginIntent' )
WITH (
MAX_MEMORY = 4096 KB,
EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY = 30 SECONDS,
MAX_EVENT_SIZE = 0 KB,
MEMORY_PARTITION_MODE = NONE,
TRACK_CAUSALITY = ON, --<-- relate events
STARTUP_STATE = ON --<-- ensure sessions starts after failover
)
XE 세션을 실행하고 (디버그 이벤트이므로 샘플링을 고려) 몇 가지 로그인을 수집하십시오.
여기서 sqlserver-0은 읽을 수있는 2 차이고 sqlserver-1은 1 차입니다. 여기서는 -K
스위치를 사용하여 sqlcmd
읽기 전용 응용 프로그램 의도 로그인과 일부 SQL 로그인을 시뮬레이션합니다. 읽기 전용 이벤트는 성공적인 읽기 전용 의도 로그인에서 발생합니다.
세션을 일시 중지하거나 중지하면 세션을 쿼리하고 두 이벤트를 연결하려고 시도 할 수 있습니다. 예 :
DROP TABLE IF EXISTS #tmp
SELECT IDENTITY( INT, 1, 1 ) rowId, file_offset, CAST( event_data AS XML ) AS event_data
INTO #tmp
FROM sys.fn_xe_file_target_read_file( 'xe_watchLoginIntent*.xel', NULL, NULL, NULL )
ALTER TABLE #tmp ADD PRIMARY KEY ( rowId );
CREATE PRIMARY XML INDEX _pxmlidx_tmp ON #tmp ( event_data );
-- Pair up the login and read_only_route_complete events via xxx
DROP TABLE IF EXISTS #users
SELECT
rowId,
event_data.value('(event/@timestamp)[1]', 'DATETIME2' ) AS [timestamp],
event_data.value('(event/action[@name="username"]/value/text())[1]', 'VARCHAR(100)' ) AS username,
event_data.value('(event/action[@name="attach_activity_id_xfer"]/value/text())[1]', 'VARCHAR(100)' ) AS attach_activity_id_xfer,
event_data.value('(event/action[@name="attach_activity_id"]/value/text())[1]', 'VARCHAR(100)' ) AS attach_activity_id
INTO #users
FROM #tmp l
WHERE l.event_data.exist('event[@name="login"]') = 1
AND l.event_data.exist('(event/action[@name="username"]/value/text())[. = "SqlUserShouldBeReadOnly"]') = 1
DROP TABLE IF EXISTS #readonly
SELECT *,
event_data.value('(event/@timestamp)[1]', 'DATETIME2' ) AS [timestamp],
event_data.value('(event/data[@name="route_port"]/value/text())[1]', 'INT' ) AS route_port,
event_data.value('(event/data[@name="route_server_name"]/value/text())[1]', 'VARCHAR(100)' ) AS route_server_name,
event_data.value('(event/action[@name="username"]/value/text())[1]', 'VARCHAR(100)' ) AS username,
event_data.value('(event/action[@name="client_app_name"]/value/text())[1]', 'VARCHAR(100)' ) AS client_app_name,
event_data.value('(event/action[@name="attach_activity_id_xfer"]/value/text())[1]', 'VARCHAR(100)' ) AS attach_activity_id_xfer,
event_data.value('(event/action[@name="attach_activity_id"]/value/text())[1]', 'VARCHAR(100)' ) AS attach_activity_id
INTO #readonly
FROM #tmp
WHERE event_data.exist('event[@name="read_only_route_complete"]') = 1
SELECT *
FROM #users u
LEFT JOIN #readonly r ON u.attach_activity_id_xfer = r.attach_activity_id_xfer
SELECT u.username, COUNT(*) AS logins, COUNT( DISTINCT r.rowId ) AS records
FROM #users u
LEFT JOIN #readonly r ON u.attach_activity_id_xfer = r.attach_activity_id_xfer
GROUP BY u.username
쿼리에는 응용 프로그램 읽기 전용 의도가 있거나없는 로그인이 표시되어야합니다.
read_only_route_complete
디버그 이벤트이므로 드물게 사용하십시오. 예를 들어 샘플링을 고려하십시오.
- 트랙 인과성과 함께 두 이벤트는 귀하의 요구 사항을 충족시킬 수있는 잠재력을 제공합니다-이 간단한 리그에서 추가 테스트가 필요합니다
- 데이터베이스 이름이 연결에 지정되어 있지 않으면 작동하지 않는 것으로 나타났습니다.
pair_matching
목표물을 작동 시키려고했지만 시간이 부족합니다. 여기에는 다음과 같은 개발 가능성이 있습니다.
ALTER EVENT SESSION [xe_watchLoginIntent] ON SERVER
ADD TARGET package0.pair_matching (
SET begin_event = N'sqlserver.login',
begin_matching_actions = N'sqlserver.username',
end_event = N'sqlserver.read_only_route_complete',
end_matching_actions = N'sqlserver.username'
)