Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Một thay đổi quan trọng đối với Sự kiện mở rộng trong SQL Server 2012

Như bạn chắc chắn đã từng nghe ở những nơi khác, SQL Server 2012 cuối cùng đã cung cấp phiên bản Sự kiện mở rộng là một giải pháp thay thế khả thi cho SQL Trace, về cả hiệu suất tốt hơn và tính chẵn lẻ của sự kiện. Có những cải tiến khác như giao diện người dùng có thể sử dụng trong Management Studio - trước đây hy vọng duy nhất của bạn cho điều này là Người quản lý sự kiện mở rộng của Jonathan Kehayias. Ngoài ra còn có một sự thay đổi lớn liên quan đến quyền:trong SQL Server 2012, bạn chỉ cần ALTER ANY EVENT SESSION để tạo và quản lý các phiên Sự kiện mở rộng (trước đây bạn cần CONTROL SERVER ).

Gần đây, tôi đã bắt gặp một sự thay đổi hành vi tinh tế hơn khiến có vẻ như phiên sự kiện của tôi đã giảm sự kiện. Bản thân sự thay đổi không phải là một bí mật và trên thực tế, ngay cả khi đã đọc hoặc nghe về sự thay đổi này nhiều lần (Jonathan nhắc tôi rằng anh ấy cũng đã nói với tôi về sự thay đổi này), tôi vẫn bỏ lỡ nó trong lần khắc phục sự cố ban đầu của mình vì vào thời điểm đó, nó không phải là một thay đổi mà tôi nghĩ sẽ ảnh hưởng đến tôi. Lo và kìa…

TL; Phiên bản DR

Trong SQL Server 2012, phiên sự kiện của bạn sẽ chỉ nắm bắt 1.000 sự kiện theo mặc định nếu nó sử dụng ring_buffer target (và 10.000 cho pair_matching ). Đây là một sự thay đổi so với 2008/2008 R2, nơi nó chỉ bị giới hạn bởi bộ nhớ. (Thay đổi được đề cập gần như trong chú thích cuối trang ở đây, hồi tháng 7 năm 2011.) Để ghi đè mặc định, bạn có thể sử dụng MAX_EVENTS_LIMIT - nhưng lưu ý rằng cài đặt này sẽ không được SQL Server 2008/2008 R2 nhận dạng, vì vậy nếu bạn có mã cần hoạt động với nhiều phiên bản, bạn sẽ cần sử dụng điều kiện.

Thêm chi tiết

Kịch bản mà tôi đang làm việc phức tạp hơn thế này, nhưng để giải thích vấn đề này, hãy giả sử một trường hợp sử dụng rất đơn giản cho Sự kiện mở rộng:theo dõi ai đang sửa đổi đối tượng. Có một phương tiện hữu ích cho việc này:object_altered . Chúng ta có thể thấy mô tả cho sự kiện này từ truy vấn sau:

SELECT description FROM sys.dm_xe_objects WHERE name = 'object_altered';
Xảy ra khi một đối tượng bị thay đổi bởi câu lệnh ALTER. Sự kiện này được nâng lên hai lần cho mỗi hoạt động ALTER. Sự kiện được đưa ra khi hoạt động bắt đầu và khi hoạt động được khôi phục hoặc được cam kết. Thêm hành động nt_username hoặc server_principal_name vào sự kiện này để xác định ai đã thay đổi đối tượng.

Vì vậy, nếu một đối tượng được sửa đổi, ví dụ, 20 lần, tôi sẽ mong đợi kéo được 40 sự kiện. Và đây chính xác là những gì xảy ra trong SQL Server 2008, 2008 R2 và 2012. Thách thức xảy ra khi có hơn 500 sửa đổi xảy ra (dẫn đến hơn 1.000 sự kiện). Trong SQL Server 2008 và 2008 R2, chúng tôi vẫn nắm bắt tất cả các sự kiện. Nhưng SQL Server 2012 sẽ giảm một số do thay đổi trong ring_buffer Mục tiêu. Để chứng minh, chúng ta hãy xây dựng một phiên sự kiện mẫu, nhanh chóng giao dịch hiệu suất để ngăn ngừa các sự kiện thua lỗ (lưu ý rằng đây không phải là tập hợp các tùy chọn mà tôi sẽ chỉ định cho bất kỳ hệ thống sản xuất nào):

USE master;
GO
CREATE EVENT SESSION [XE_Alter] ON SERVER
ADD EVENT  sqlserver.object_altered
(
    ACTION (sqlserver.server_principal_name)
    WHERE  (sqlserver.session_id = 78) -- change 78 to your current spid
)
ADD TARGET package0.ring_buffer (SET MAX_MEMORY = 4096)
WITH (EVENT_RETENTION_MODE = NO_EVENT_LOSS, MAX_DISPATCH_LATENCY = 5 SECONDS);
 
ALTER EVENT SESSION [XE_Alter] ON SERVER STATE = START;
GO

Khi phiên bắt đầu, trong cùng một cửa sổ, hãy chạy tập lệnh sau, tập lệnh này tạo hai thủ tục và thay đổi chúng trong một vòng lặp.

CREATE PROCEDURE dbo.foo_x AS SELECT 1;
GO
 
CREATE PROCEDURE dbo.foo_y AS SELECT 1;
GO
 
ALTER PROCEDURE dbo.foo_x AS SELECT 2;
GO 275
 
ALTER PROCEDURE dbo.foo_y AS SELECT 2;
GO 275
 
DROP PROCEDURE dbo.foo_x, dbo.foo_y;
GO

Bây giờ, hãy kéo tên đối tượng và mỗi đối tượng đã được sửa đổi bao nhiêu lần khỏi mục tiêu và bỏ phiên sự kiện (hãy kiên nhẫn; trên hệ thống của tôi, quá trình này thường xuyên mất khoảng 40 giây):

;WITH raw_data(t) AS
(
  SELECT CONVERT(XML, target_data)
  FROM sys.dm_xe_sessions AS s
  INNER JOIN sys.dm_xe_session_targets AS st
  ON s.[address] = st.event_session_address
  WHERE s.name = 'XE_Alter'
  AND st.target_name = 'ring_buffer'
),
xml_data (ed) AS
(
  SELECT e.query('.') 
  FROM raw_data 
  CROSS APPLY t.nodes('RingBufferTarget/event') AS x(e)
)
SELECT [object_name] = obj, event_count = COUNT(*)
FROM
(
  SELECT
    --[login] = ed.value('(event/action[@name="server_principal_name"]/value)[1]', 'nvarchar(128)'),
    obj   = ed.value('(event/data[@name="object_name"]/value)[1]', 'nvarchar(128)'),
    phase = ed.value('(event/data[@name="ddl_phase"]/text)[1]',    'nvarchar(128)')
  FROM xml_data
) AS x
WHERE phase = 'Commit'
GROUP BY obj;
GO
 
DROP EVENT SESSION [XE_Alter] ON SERVER;
GO

Kết quả (bỏ qua chính xác một nửa trong số 1.000 sự kiện được ghi lại, tập trung vào Commit chỉ sự kiện):

object_name event_count
===========================
foo_x 225
foo_y 275

Điều này cho thấy rằng 50 sự kiện cam kết (tổng số 100 sự kiện) đã bị loại bỏ cho foo_x , và tổng số chính xác 1.000 sự kiện đã được thu thập ((225 + 275) * 2)). SQL Server dường như tự ý quyết định loại sự kiện nào - về lý thuyết, nếu nó đang thu thập 1.000 sự kiện và sau đó dừng lại, tôi sẽ có 275 sự kiện cho foo_x và 225 cho foo_y , vì tôi đã thay đổi foo_x đầu tiên, và tôi không nên đạt đến giới hạn cho đến khi vòng lặp đó được hoàn thành. Nhưng rõ ràng là có một số cơ chế khác đang diễn ra ở đây trong cách XEvents quyết định sự kiện nào nên giữ lại và sự kiện nào nên loại bỏ.

Trong mọi trường hợp, bạn có thể giải quyết vấn đề này bằng cách chỉ định một giá trị khác cho MAX_EVENTS_LIMIT trong ADD TARGET một phần của mã:

-- ...
ADD TARGET package0.ring_buffer (SET MAX_MEMORY = 4096, MAX_EVENTS_LIMIT = 0)
------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^
-- ...

Lưu ý rằng 0 =không giới hạn, nhưng bạn có thể chỉ định bất kỳ giá trị số nguyên nào. Khi chúng tôi chạy thử nghiệm của mình ở trên với cài đặt mới, chúng tôi thấy kết quả chính xác hơn, vì không có sự kiện nào bị bỏ qua:

object_name event_count
===========================
foo_x 275
foo_y 275

Như đã đề cập ở trên, nếu bạn cố gắng sử dụng thuộc tính này khi tạo phiên sự kiện chống lại SQL Server 2008/2008 R2, bạn sẽ gặp lỗi này:

Tin nhắn 25629, Mức 16, Trạng thái 1, Dòng 1
Đối với mục tiêu, "package0.ring_buffer", thuộc tính có thể tùy chỉnh, "MAX_EVENTS_LIMIT", không tồn tại.

Vì vậy, nếu bạn đang thực hiện bất kỳ loại tạo mã nào và muốn hành vi nhất quán giữa các phiên bản, trước tiên bạn sẽ phải kiểm tra phiên bản và chỉ bao gồm thuộc tính cho năm 2012 trở lên.

Kết luận

Nếu bạn đang nâng cấp từ SQL Server 2008/2008 R2 lên 2012 hoặc đã viết mã Sự kiện mở rộng nhắm mục tiêu nhiều phiên bản, bạn nên biết về sự thay đổi hành vi này và viết mã cho phù hợp. Nếu không, bạn có nguy cơ bỏ các sự kiện, ngay cả trong các tình huống mà bạn cho rằng - và nơi mà hành vi trước đó sẽ ngụ ý - là không thể thực hiện được các sự kiện bị bỏ. Đây không phải là thứ mà các công cụ như Cố vấn nâng cấp hoặc Trình phân tích các phương pháp hay nhất sẽ chỉ ra cho bạn.

Cơ chế cơ bản xung quanh vấn đề này được mô tả chi tiết trong báo cáo lỗi này và bài đăng trên blog này.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lấy múi giờ hiện tại của máy chủ trong SQL Server (T-SQL)

  2. Xuất dữ liệu bảng từ SQL Server này sang SQL Server khác

  3. Tạo kế hoạch bảo trì trong SQL Server

  4. Cách tham gia vào hàng đầu tiên

  5. Cách tốt nhất để tạo và điền một bảng số là gì?