การเลือกใช้งานsqlserver.read_only_route_complete
Extended Event ที่ Kin และ Remus พูดถึงนั้นเป็นDebug ที่ดีแต่มันไม่ได้มีข้อมูลมากมาย - 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 เป็นของฉันรองอ่านและ sqlserver-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'
)