sqlserver.read_only_route_complete
परिजनों और रेमस द्वारा उल्लिखित विस्तारित घटना पर उठाते हुए , यह एक अच्छी डेब्यू घटना है, लेकिन यह इसके साथ बहुत अधिक जानकारी नहीं रखता है - बस route_port
(उदाहरण के लिए 1433) और route_server_name
(जैसे sqlserver-0.contoso.com) डिफ़ॉल्ट रूप से । यह केवल यह निर्धारित करने में भी मदद करेगा कि एक रीड-ओनली इंटेंस कनेक्शन सफल था। एक read_only_route_fail
घटना है, लेकिन मैं इसे फायर नहीं कर सका, हो सकता है कि रूटिंग यूआरएल के साथ कोई समस्या हो, जब तक मैं बता सकता हूं तब तक माध्यमिक उदाहरण अनुपलब्ध / बंद होने पर आग नहीं लगती थी।
हालाँकि, मुझे कुछ सफलता मिली है जो इस 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'
)