AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 139187
Accepted
Michael Cherevko
Michael Cherevko
Asked: 2016-05-22 21:51:10 +0800 CST2016-05-22 21:51:10 +0800 CST 2016-05-22 21:51:10 +0800 CST

Capturar duas mensagens de erro/jogar na tabela

  • 772

Meu objetivo é detectar erros de tarefas de backup na tabela de monitoramento.
O problema é que há casos em que a instrução de backup retorna mais de um erro, então ERROR_MESSAGE() não é suficiente:

Msg 3201, Nível 16, Estado 1, Linha 1 Não é possível abrir o dispositivo de backup '...' Erro 3 do sistema operacional (O sistema não pode encontrar o caminho especificado.).

Msg 3013, Nível 16, Estado 1, Linha 1 BACKUP DATABASE está terminando de forma anormal.

Posso usar o throw para capturar as duas mensagens, mas existe uma maneira fácil de inserir a saída do throw na tabela ou superar esse problema de outra maneira?

sql-server sql-server-2014
  • 3 3 respostas
  • 1773 Views

3 respostas

  • Voted
  1. Best Answer
    Dave Mason
    2016-09-16T06:23:44+08:002016-09-16T06:23:44+08:00

    Você pode aprimorar o tratamento de erros com eventos estendidos para superar a falha TRY...CATCH que está enfrentando. O padrão de design envolve estas etapas:

    1. Crie e inicie uma Sessão de Eventos Estendidos: ela irá capturar sqlserver.error_reportedeventos, filtrados principalmente por SPID.
    2. Execute uma instrução em um TRYbloco.
    3. Dentro (ou depois) do CATCHbloco, leia os dados da sessão XEvents.
    4. Use os dados disponíveis para responder ao(s) erro(s) conforme apropriado.
    5. Pare e elimine a sessão XEvents.

    Aqui está um exemplo que pode ser executado manualmente em um único lote do SSMS. Apenas certifique-se de substituir todas as ocorrências de "2016" no script pelo seu SPID.

    CREATE EVENT SESSION [Error Handling Session(2016)]
    ON SERVER 
    ADD EVENT sqlserver.error_reported
    (
        ACTION(
            sqlserver.session_id,
            sqlserver.sql_text
        )
        WHERE [package0].[not_equal_unicode_string]([message],N'''''') 
        AND [severity]>(10) 
        AND [sqlserver].[session_id]=(2016)
    ) 
    ADD TARGET package0.ring_buffer
    WITH (
        --ALLOW_SINGLE_EVENT_LOSS
        --NO_EVENT_LOSS
        EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
    
        MAX_MEMORY=4096 KB,
        MAX_DISPATCH_LATENCY=1 SECONDS,
        MAX_EVENT_SIZE=0 KB,
        MEMORY_PARTITION_MODE=NONE,
        TRACK_CAUSALITY=ON,
        STARTUP_STATE=OFF
    );
    
    ALTER EVENT SESSION [Error Handling Session(2016)] ON SERVER STATE=START;
    
    BEGIN TRY
        BACKUP DATABASE master
        TO DISK = 'master.diff.bak'
        WITH DIFFERENTIAL;
    END TRY
    BEGIN CATCH
        DECLARE @XEData XML
    
        SELECT @XEData = CAST(xet.target_data AS XML)
        FROM sys.dm_xe_session_targets AS xet
        JOIN sys.dm_xe_sessions AS xe
            ON (xe.address = xet.event_session_address)
        WHERE xe.name = 'Error Handling Session(2016)';
    
        /*
        Check value of "totalEventsProcessed" to ensure events have been 
        dispatched to event session target (ring_buffer).
        If no events have been processed, delay for a period of MAX_DISPATCH_LATENCY +1 (in seconds).
        */
        IF @XEData.value('(/RingBufferTarget/@totalEventsProcessed)[1]', 'INT') = 0
        BEGIN
            WAITFOR DELAY '00:00:02';
    
            SELECT @XEData = CAST(xet.target_data AS XML)
            FROM sys.dm_xe_session_targets AS xet
            JOIN sys.dm_xe_sessions AS xe
                ON (xe.address = xet.event_session_address)
            WHERE xe.name = 'Error Handling Session(2016)';
        END
    
        --Comment/uncomment as desired to show the formatted XML session data.
        SELECT @XEData;
    
        --Shred the XML. Do whatever you want with this data: 
        -- log it to a table, create and send an email alert, etc.
        SELECT 
            x.c.value(N'(@name)[1]', N'NVARCHAR(MAX)') AS EventName,
            x.c.value(N'(@timestamp)[1]', N'datetime') AS EventTime,
            x.c.value(N'(data[@name="error_number"]/value)[1]', N'NVARCHAR(MAX)') AS ErrorNumber,
            x.c.value(N'(data[@name="severity"]/value)[1]', N'NVARCHAR(MAX)') AS Severity,
            x.c.value(N'(data[@name="state"]/value)[1]', N'NVARCHAR(MAX)') AS [State],
            x.c.value(N'(data[@name="user_defined"]/value)[1]', N'NVARCHAR(MAX)') AS UserDefined,
            x.c.value(N'(data[@name="category"]/text)[1]', N'NVARCHAR(MAX)') AS Category,
            x.c.value(N'(data[@name="destination"]/text)[1]', N'NVARCHAR(MAX)') AS Destination,
            x.c.value(N'(data[@name="is_intercepted"]/value)[1]', N'NVARCHAR(MAX)') AS IsIntercepted,
            x.c.value(N'(data[@name="message"]/value)[1]', N'NVARCHAR(MAX)') AS [Message],
            x.c.value(N'(action[@name="sql_text"]/value)[1]', N'NVARCHAR(MAX)') AS SqlText,
            x.c.value(N'(action[@name="session_id"]/value)[1]', N'NVARCHAR(MAX)') AS SessionId
        FROM @XEData.nodes('//RingBufferTarget/event') AS x(c)
        --WHERE x.c.value(N'(data[@name="destination"]/text)[1]', N'NVARCHAR(MAX)') = 'USER'
    
    END CATCH
    
    ALTER EVENT SESSION [Error Handling Session(2016)] ON SERVER STATE=STOP;
    DROP EVENT SESSION [Error Handling Session(2016)] ON SERVER;
    GO
    

    Depois de executar o script, a saída do SSMS deve ser semelhante a esta: insira a descrição da imagem aqui

    Há muitas partes móveis lá. Mas você pode ser capaz de fazê-lo funcionar para você. Eu escrevi algumas postagens de blog relacionadas sobre TRY...CATCH que podem ser úteis:

    A promessa não cumprida de TRY...CATCH

    Tratamento de erros T-SQL aprimorado com eventos estendidos

    Parte 2: Tratamento de erros de T-SQL aprimorado com eventos estendidos

    • 3
  2. IT Thug Ninja
    2016-05-22T22:40:27+08:002016-05-22T22:40:27+08:00

    O problema é que há casos em que a instrução de backup retorna mais de um erro, então ERROR_MESSAGE() não é suficiente.

    No trabalho do SQL Agent que você usa para fazer backup de seus bancos de dados com dispositivos de backup, apenas faça com que cada etapa passe para a próxima etapa, com falha ou sucesso. No entanto, faça com que a última etapa tenha a lógica abaixo e diga a ela para relatar falha em falha e relatar sucesso em sucesso .

    Isso enviará a você por e-mail os detalhes da falha das tabelas msdb para esse trabalho, como você veria na área do histórico de trabalhos do SQL Agent para os registros de data atuais. Você sempre pode verificar o histórico do SQL Agent manualmente quando receber a notificação por e-mail, mas isso funciona bem para a necessidade em que o configurei.

    Tenho certeza de que você também pode usar a lógica e fazer algumas alterações para atender às suas necessidades. No meu caso, cada tarefa de backup para o dispositivo de backup é uma etapa separada, cada uma passando para a próxima etapa, independentemente dos resultados, e a última etapa é como indiquei acima e é suficiente para o monitoramento de falhas.

    Se eu não estiver no escritório ou por conexão VPN, os dados da tabela HTML enviados por e-mail me darão uma ideia se isso precisa de atenção e assim por diante, verificando o Outlook Web Mail.

    WAITFOR DELAY '00:00:10'  ----ten second pause to ensure everything needed is written to table
    SELECT  step_name, message
    FROM    msdb.dbo.sysjobhistory
    WHERE   instance_id > COALESCE((SELECT MAX(instance_id) FROM msdb.dbo.sysjobhistory
                                    WHERE job_id = $(ESCAPE_SQUOTE(JOBID)) AND step_id = 0), 0)
            AND job_id = $(ESCAPE_SQUOTE(JOBID))
            AND run_status <> 1 -- success
    
    IF      @@ROWCOUNT <> 0
    BEGIN
            RAISERROR('*** SQL Agent Job Prior Step Failure Occurred ***', 16, 1)
    
    DECLARE @job_name NVARCHAR(256) = (SELECT name FROM msdb.dbo.sysjobs WHERE job_id = $(ESCAPE_SQUOTE(JOBID)))
    DECLARE @email_profile NVARCHAR(256) = 'SQLInstance Name Alerts'
    DECLARE @emailrecipients NVARCHAR(500) = '[email protected]'
    DECLARE @subject NVARCHAR(MAX) = 'SQL Server Agent Job Failure Report: ' + @@SERVERNAME
    DECLARE @msgbodynontable NVARCHAR(MAX) = 'SQL Server Agent Job Failure Report For: "' + @job_name + '"'
    
    --Dump report data to a temp table to be put into XML formatted HTML table to email out
    SELECT sjh.[server]
        ,sj.NAME
        ,sjh.step_id
        ,sjh.[message]
        ,sjh.run_date
        ,sjh.run_time
    INTO #TempJobFailRpt
    FROM msdb..sysjobhistory sjh
    INNER JOIN msdb..sysjobs sj ON (sj.job_id = sjh.job_id)
    WHERE run_date = convert(INT, convert(VARCHAR(8), getdate(), 112))
        AND run_status != 4 -- Do not show status of 4 meaning in progress steps
        AND run_status != 1 -- Do not show status of 1 meaning success
        AND NAME = @job_name
    ORDER BY run_date
    
    IF EXISTS (
            SELECT *
            FROM #TempJobFailRpt
            )
    BEGIN
    
    -----Build report to HTML formatted email using FOR XML PATH
    DECLARE @tableHTML NVARCHAR(MAX) = '
    <html>
    <body>
        <H1>' + @msgbodynontable + '</H1>
            <table border="1" style=
            "background-color: #C0C0C0; border-collapse: collapse">
            <caption style="font-weight: bold">
                    ****** Below is the SQL Agent history detail from the SQL Agent job named: ''' + @job_name + ''' . ******
            </caption>
    
    <tr>
        <th style="width:25%; text-decoration: underline">SQL Instance</th>
        <th style="text-decoration: underline">Job Name</th>
        <th style="text-decoration: underline">Step</th>
        <th style="text-decoration: underline">Message Text</th>
        <th style="text-decoration: underline">Job Run Date</th>
        <th style="text-decoration: underline">Job Run Time</th>
    </tr>' + CAST((
                SELECT td = [server]
                    ,''
                    ,td = NAME
                    ,''
                    ,td = step_id
                    ,''
                    ,td = [message]
                    ,''
                    ,td = run_date
                    ,''
                    ,td = run_time
                FROM #TempJobFailRpt a
                ORDER BY run_date
                FOR XML PATH('tr')
                    ,TYPE
                    ,ELEMENTS XSINIL -- brings back non isnull NULL column values as empty without making HTML table look odd for empty value otherwise
                ) AS NVARCHAR(MAX)) + '
        </table>
    </body>
    </html>';
    
    EXEC msdb.dbo.sp_send_dbmail @profile_name = @email_profile
        ,@recipients = @emailrecipients
        ,@subject = @subject
        ,@body = @tableHTML
        ,@body_format = 'HTML'
    
    --Drop Temp table
        DROP TABLE #TempJobFailRpt
    END
    ELSE
    BEGIN
        PRINT '*** No Records Generated ***' 
        DROP TABLE #TempJobFailRpt
    END
    END
    
    • 0
  3. Michael Cherevko
    2016-09-21T00:37:49+08:002016-09-21T00:37:49+08:00

    Consulta do DMason com alça spid:

    DECLARE @Spid varchar(6)
    DECLARE @Sql varchar(max)
    SELECT @Spid = @@spid
    SET @sql = 
    'CREATE EVENT SESSION [Error Handling Session(' + @spid + ')]
    ON SERVER 
    ADD EVENT sqlserver.error_reported
    (
        ACTION(
            sqlserver.session_id,
            sqlserver.sql_text
        )
        WHERE [package0].[not_equal_unicode_string]([message],N'''''''''''') 
        AND [severity]>(10) 
        AND [sqlserver].[session_id]=(' + @spid + ')
    ) 
    ADD TARGET package0.ring_buffer
    WITH (
        --ALLOW_SINGLE_EVENT_LOSS
        --NO_EVENT_LOSS
        EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
    
        MAX_MEMORY=4096 KB,
        MAX_DISPATCH_LATENCY=1 SECONDS,
        MAX_EVENT_SIZE=0 KB,
        MEMORY_PARTITION_MODE=NONE,
        TRACK_CAUSALITY=ON,
        STARTUP_STATE=OFF
    );
    
    ALTER EVENT SESSION [Error Handling Session(' + @spid + ')] ON SERVER STATE=START;'
    EXEC(@Sql)
    BEGIN TRY
        BACKUP DATABASE master
        TO DISK = 'master.diff.bak'
        WITH DIFFERENTIAL;
    END TRY
    BEGIN CATCH
        DECLARE @XEData XML
        DECLARE @XEName varchar(100) = 'Error Handling Session(' + @spid + ')' 
    
        SELECT @XEData = CAST(xet.target_data AS XML)
        FROM sys.dm_xe_session_targets AS xet
        JOIN sys.dm_xe_sessions AS xe
            ON (xe.address = xet.event_session_address)
        WHERE xe.name = @XEName;
    
        /*
        Check value of "totalEventsProcessed" to ensure events have been 
        dispatched to event session target (ring_buffer).
        If no events have been processed, delay for a period of MAX_DISPATCH_LATENCY +1 (in seconds).
        */
        IF @XEData.value('(/RingBufferTarget/@totalEventsProcessed)[1]', 'INT') = 0
        BEGIN
            WAITFOR DELAY '00:00:02';
    
            SELECT @XEData = CAST(xet.target_data AS XML)
            FROM sys.dm_xe_session_targets AS xet
            JOIN sys.dm_xe_sessions AS xe
                ON (xe.address = xet.event_session_address)
            WHERE xe.name = @XEName;
        END
    
        --Comment/uncomment as desired to show the formatted XML session data.
        SELECT @XEData;
    
        --Shred the XML. Do whatever you want with this data: 
        -- log it to a table, create and send an email alert, etc.
        SELECT 
            x.c.value(N'(@name)[1]', N'NVARCHAR(MAX)') AS EventName,
            x.c.value(N'(@timestamp)[1]', N'datetime') AS EventTime,
            x.c.value(N'(data[@name="error_number"]/value)[1]', N'NVARCHAR(MAX)') AS ErrorNumber,
            x.c.value(N'(data[@name="severity"]/value)[1]', N'NVARCHAR(MAX)') AS Severity,
            x.c.value(N'(data[@name="state"]/value)[1]', N'NVARCHAR(MAX)') AS [State],
            x.c.value(N'(data[@name="user_defined"]/value)[1]', N'NVARCHAR(MAX)') AS UserDefined,
            x.c.value(N'(data[@name="category"]/text)[1]', N'NVARCHAR(MAX)') AS Category,
            x.c.value(N'(data[@name="destination"]/text)[1]', N'NVARCHAR(MAX)') AS Destination,
            x.c.value(N'(data[@name="is_intercepted"]/value)[1]', N'NVARCHAR(MAX)') AS IsIntercepted,
            x.c.value(N'(data[@name="message"]/value)[1]', N'NVARCHAR(MAX)') AS [Message],
            x.c.value(N'(action[@name="sql_text"]/value)[1]', N'NVARCHAR(MAX)') AS SqlText,
            x.c.value(N'(action[@name="session_id"]/value)[1]', N'NVARCHAR(MAX)') AS SessionId
        FROM @XEData.nodes('//RingBufferTarget/event') AS x(c)
        --WHERE x.c.value(N'(data[@name="destination"]/text)[1]', N'NVARCHAR(MAX)') = 'USER'
    
    END CATCH
    SET @Sql = 
    'ALTER EVENT SESSION [Error Handling Session(' + @Spid + ')] ON SERVER STATE=STOP;
    DROP EVENT SESSION [Error Handling Session(' + @Spid + ')] ON SERVER;'
    EXEC(@sql)
    GO
    
    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve