扩展事件之外的非法 XML 字符

Rbj*_*bjz 6 sql-server-2008

我正在捕获 SQL 服务器中的扩展事件。尝试分析跟踪 - 将事件数据转换为 xml 出现错误:

消息 9420,级别 16,状态 1,第 28 行
XML 解析:第 1 行,字符 731,非法 xml 字符

排查问题,发现sql_text action 值中有一个ascii 数字3 的字符。该值由客户端以动态 SQL 的形式传递。这在这里几乎不用担心。问题是 XE 无法处理 sql_text 中的奇怪字符。

这就是我获取导致问题的数据的方式:

declare @data nvarchar(max)
declare @id int
SET NOCOUNT ON

if object_id('tempdb.dbo.#xerrors') is null --drop table #xerrors
begin
    select CAST(null as XML) as xml_event_data, * 
    into #xerrors
    from sys.fn_xe_file_target_read_file
            (
                '...\Log\error_*.xet', 
                '...\Log\error_*.xem', 
                null, 
                null
            ) 

    alter table #xerrors
    add id int identity(1,1) primary key not null

end

while exists(select 1 from #xerrors where (@id is null or ID > @id) and xml_event_data is null)
begin
    select top 1 @id = id, @data = event_data from #xerrors where (@id is null or ID > @id) and xml_event_data is null order by id

    print @id

    update #xerrors set xml_event_data = CONVERT(xml, event_data) where id = @id

end

select ascii(SUBSTRING(event_data, 731, 1)), event_data from #xerrors where id = 11253
Run Code Online (Sandbox Code Playgroud)

我的会话设置是:

-- TRIES TO ELIMINATE PREVIOUS SESSIONS
if exists(select 1 from sys.dm_xe_sessions xes where xes.name = 'error_capture')
      DROP EVENT SESSION error_capture ON SERVER
GO


-- CREATES THE SESSION
CREATE EVENT SESSION error_capture ON SERVER
ADD EVENT sqlserver.error_reported
(
    ACTION (
        sqlserver.tsql_stack, 
        sqlserver.sql_text,
        sqlserver.client_hostname,
        sqlserver.client_pid,
        sqlserver.client_app_name,
        sqlserver.is_system,
        sqlserver.nt_username,
        sqlserver.username,
        sqlserver.transaction_id,
        sqlserver.session_id,
        sqlserver.database_id,
        sqlserver.database_context
    )
    --actions
    WHERE Severity > 10
)
ADD TARGET package0.asynchronous_file_target
-- CONFIGURES THE FILE TARGET
(set filename = '...\Log\error.xet' , metadatafile = '...\Log\error.xem')
GO

-- STARTS THE SESSION
ALTER EVENT SESSION error_capture ON SERVER STATE = START
Run Code Online (Sandbox Code Playgroud)

您认为这是 XE 框架中的错误还是我做错了什么?我相信所有事件都应该是有效的 XML ...

文件路径已被有意缩短

Rbj*_*bjz 3

由于还没有接受者,我提供一个猜测答案:是的,我认为这是一个错误。

解决方法:在知道非法字符后将其替换,然后再将数据转换为 XML,如下所示:

select xml_event_data = CONVERT(xml, replace(event_data,CHAR(3),'')), *
from sys.fn_xe_file_target_read_file
            (
                '...\Log\error_*.xet', 
                '...\Log\error_*.xem', 
                null, 
                null
            ) 
Run Code Online (Sandbox Code Playgroud)