排查数据库邮件问题

本文提供了排查数据库邮件问题的方法。 如果 初始故障排除 尚未解决问题,请使用 高级故障排除

初始数据库邮件故障排除

下面是基本故障排除步骤:

  1. 查看已使用 DatabaseMail.exe 发送或尝试发送的邮件的数据库邮件日志和 sysmail (sysmail_event_log) 视图。
  2. 发送测试邮件。 如果测试邮件已成功发送,则重点关注未发送的邮件的详细信息。 如果未发送测试邮件,请专注于对测试邮件进行故障排除,并忽略之前未成功发送的邮件。
  3. 如果怀疑 SMTP 服务器设置不正确,或者用于发送邮件的帐户出现问题,请使用 PowerShell 发送测试邮件。
  4. 如果无法使用 PowerShell 发送邮件,则可能是 SMTP 配置问题,并且需要 SMTP 管理员。

可以使用以下步骤进行初始数据库邮件故障排除。

Msdb sysmail 系统视图

在查看详细步骤之前,下面是相关数据库邮件系统视图的快速摘要。

  1. 大多数相关的日志记录发生在 msdb sysmail 系统视图中。 可以直接在环境中查询这些视图。

    名称 Type 描述
    sysmail_allitems 视图 列出提交到数据库邮件的所有邮件。
    sysmail_event_log 视图 列出有关数据库邮件外部程序行为的消息。
    sysmail_faileditems 视图 有关数据库邮件无法发送的消息的信息。
    sysmail_mailattachments 视图 有关数据库邮件附件的信息。
    sysmail_sentitems 视图 有关已使用 数据库邮件 发送的消息的信息。
    sysmail_unsentitems 视图 有关数据库邮件当前正在尝试发送的消息的信息。
  2. Windows 应用程序事件日志中记录了一些错误。

步骤 1:检查sysmail_event_log视图

此系统视图是对所有数据库邮件问题进行故障排除的起点。

排查数据库邮件问题时,请在sysmail_event_log视图中搜索与电子邮件失败相关的事件。 某些消息(如数据库邮件外部程序失败)与特定电子邮件无关。

Sysmail_event_log包含数据库邮件系统返回的每个 Windows 或 SQL Server 消息的一行。 在 SQL Server Management Studio(SSMS)中,选择“管理”,右键单击数据库邮件,然后选择“查看数据库邮件日志”以检查数据库邮件日志,如下所示:

数据库邮件菜单中“查看数据库邮件日志项”的屏幕截图。

运行以下查询以 sysmail_event_log执行以下操作:

SELECT er.log_id AS [LogID],
  er.event_type AS [EventType],
  er.log_date AS [LogDate],
  er.description AS [Description],
  er.process_id AS [ProcessID],
  er.mailitem_id AS [MailItemID],
  er.account_id AS [AccountID],
  er.last_mod_date AS [LastModifiedDate],
  er.last_mod_user AS [LastModifiedUser]
FROM msdb.dbo.sysmail_event_log er
ORDER BY [LogDate] DESC

event_type 列可以具有以下值:

  • 错误
  • 警告
  • 信息
  • 成功

若要仅显示所需的事件类型,请使用子 WHERE 句进行筛选。

检查特定失败的邮件项目

若要搜索与特定电子邮件相关的错误,请在视图中查找mailitem_id失败的电子邮件sysmail_faileditems,然后搜索与其中sysmail_event_log相关的mailitem_id邮件。

SELECT er.log_id AS [LogID], 
    er.event_type AS [EventType], 
    er.log_date AS [LogDate], 
    er.description AS [Description], 
    er.process_id AS [ProcessID], 
    er.mailitem_id AS [MailItemID], 
    er.account_id AS [AccountID], 
    er.last_mod_date AS [LastModifiedDate], 
    er.last_mod_user AS [LastModifiedUser],
    fi.send_request_user,
    fi.send_request_date,
    fi.recipients, fi.subject, fi.body
FROM msdb.dbo.sysmail_event_log er 
    LEFT JOIN msdb.dbo.sysmail_faileditems fi
ON er.mailitem_id = fi.mailitem_id
ORDER BY [LogDate] DESC

sp_send_dbmail中返回错误时,电子邮件不会提交到数据库邮件系统,并且错误不会显示在sysmail_event_log视图中。 应收集语句级探查器跟踪并排查遇到的错误。

当单个帐户传递尝试失败时,数据库邮件会在重试尝试期间保留错误消息,直到邮件项目传递成功或失败。 如果传递最终成功,则会将所有累积的错误记录为单独的警告,包括 account_id。 即使电子邮件已发送,也可能导致警告。 如果传递最终失败,则所有以前的警告都记录为一条 account_id 错误消息,因为所有帐户都失败。

可能记录sysmail_event_log的问题

可能会登录 sysmail_event_log以下问题:

  • DatabaseMail.exe连接到 SQL Server 失败

    如果外部程序无法记录到 msdb 表,程序会将错误记录到 Windows 应用程序事件日志。

  • 与 SMTP 服务器关联的失败。

    • 无法联系 SMTP 服务器。
    • 无法通过 SMTP 服务器进行身份验证。
    • SMTP 服务器拒绝电子邮件。
  • DatabaseMail.exe中的异常。

如果数据库邮件外部可执行文件没有问题,请转到 sysmail 系统视图。 若要搜索与特定电子邮件相关的错误,请在视图中查找mailitem_id失败的电子邮件sysmail_faileditems,然后搜索与其中sysmail_event_log相关的mailitem_id邮件。 从sp_send_dbmail中返回错误时,电子邮件不会提交到数据库邮件系统,并且错误不会显示在sysmail_event_log视图中。

步骤 2:检查sysmail_unsentitems、sysmail_sentitems和sysmail_faileditems视图

可以检查这些视图是否存在特定电子邮件的问题,以查看数据库邮件是正在发送的、是否停滞在队列中还是无法发送。

msdb 数据库中的内部表包含从数据库邮件发送的电子邮件和附件及其当前状态。 数据库邮件处理消息时更新这些表。

Sysmail_mailitems 表是其他 sysmail 视图的基表。 视图 sysmail_allitems 基于表构建,是这些视图的超集。

注意

如果将生产 msdb 数据库备份并还原到另一个测试系统作为用户数据库,则可以在还原的备份中重新创建 sysmail 系统视图。 还原备份中的视图定义将引用 还原备份的系统上的 msdb 数据库。 请参阅脚本,在 Msdb 备份部分中的客户 msdb 中重新创建 sysmail 视图。

Sysmail_unsentitems

此视图包含其状态为未发送重试的每个数据库邮件消息的一行。

如果要查看正在等待发送的消息数以及消息已在邮件队列中存在的时间,则请使用该视图。 通常,未发送的消息数较小。 可以在正常操作期间进行基准测试,以确定消息队列中正常操作的合理消息数。

如果 msdb 中的 Service Broker 对象出现问题,还可以检查邮件 sysmail_unsentitemsExternalMailQueue如果禁用或InternalMailQueue队列,或者路由出现问题,邮件可能会保留sysmail_unsentitmes

未发送重试 邮件仍位于邮件队列中,随时可以发送。 由于以下原因, 消息可能具有未发送 状态:

  • 消息为新消息。 尽管邮件已放置在邮件队列中,但数据库邮件正在处理其他邮件,但尚未到达此邮件。
  • 数据库邮件外部程序未运行,且未发送任何邮件。

消息可能具有 重试 状态,原因如下:

  • 数据库邮件尝试发送邮件,但无法联系 SMTP 邮件服务器。 数据库邮件继续尝试使用分配给发送消息的配置文件的其他数据库邮件帐户发送消息。 如果没有帐户可以发送邮件,数据库邮件将等待为Account Retry Delay参数配置的时间长度,然后再次尝试发送邮件。 数据库邮件使用参数来确定尝试发送消息的次数。 数据库邮件尝试发送消息时,该消息将保持重试状态。
  • 数据库邮件连接到 SMTP 服务器,但遇到错误。 SMTP 服务器返回的 SMTP 错误代码和任何随附的错误消息都可用于进一步进行故障排除。

Sysmail_faileditems

如果知道电子邮件无法发送,可以直接查询 sysmail_faileditems 。 有关按收件人查询sysmail_faileditems和筛选特定邮件的详细信息,请参阅检查随数据库邮件发送的 EMail 邮件的状态。

若要检查使用 数据库邮件 发送的电子邮件的状态,请运行以下脚本:

-- Show the subject, the time that the mail item row was last  
-- modified, and the log information.  
-- Join sysmail_faileditems to sysmail_event_log   
-- on the mailitem_id column.  
-- In the WHERE clause list items where danw was in the recipients,  
-- copy_recipients, or blind_copy_recipients.  
-- These are the items that would have been sent to Jane@contoso.com
 
SELECT items.subject, items.last_mod_date, l.description 
FROM dbo.sysmail_faileditems AS items  
INNER JOIN dbo.sysmail_event_log AS l ON items.mailitem_id = l.mailitem_id  
WHERE items.recipients LIKE '%Jane%'    
    OR items.copy_recipients LIKE '%Jane%'   
    OR items.blind_copy_recipients LIKE '%Jane%'  
GO  

Sysmail_sentitems

如果想要找到最后一封电子邮件成功发送的时间,可以按如下所示查询 sysmail_sentitems 和排序 sent_date

SELECT ssi.sent_date, * 
FROM msdb.dbo.sysmail_sentitems ssi
ORDER BY ssi.sent_date DESC

如果某些类型的邮件已成功发送,但其他邮件未发送,则此视图可能有助于找出差异。

步骤 3:检查sysmail_mailattachments视图

此视图包含提交到数据库邮件的每个附件的一行。 如果需要有关数据库邮件附件的信息,请使用此视图。

如果在发送带有附件的邮件时遇到问题,但某些带有附件的邮件已成功发送,此视图可能有助于找出差异。

步骤 4:检查 SMTP 服务器的数据库邮件配置

帮助解决数据库邮件问题的另一步是检查 SMTP 服务器的数据库邮件配置以及用于发送数据库邮件的帐户。

有关如何配置数据库邮件的详细信息,请参阅“配置数据库邮件”。

配置数据库邮件

若要配置数据库邮件,请执行以下步骤:

  1. 打开 SSMS,选择“管理”,右键单击数据库邮件,然后选择“配置数据库邮件”。

    数据库邮件菜单中配置数据库邮件日志项的屏幕截图。

  2. 选择“下一步管理数据库邮件帐户和配置文件>

  3. 如果你有帐户,请选择“查看”、“更改或删除现有帐户”,然后选择“下一步,否则请选择“创建新帐户”。 以下屏幕截图显示了用于连接到 SMTP 服务器的帐户设置并发送数据库邮件。

    在数据库邮件配置向导中管理现有帐户的屏幕截图。

请特别注意:

  • 服务器名称和端口号。 服务器名称必须是完全限定的域名,端口号必须准确。 通常,默认 SMTP 端口为 25,但需要检查当前的 SMTP 配置。

  • SSL。 验证 SMTP 服务器是否需要安全套接字层(SSL)还是传输层安全性(TLS)。

  • SMTP 身份验证。 是否使用数据库引擎服务的Windows 身份验证、指定的域帐户或匿名身份验证的基本身份验证? 需要验证 SMTP 服务器在自己的环境中允许的内容。 如果指定了域帐户(服务帐户或基本身份验证),则必须对 SMTP 服务器具有权限。

可以使用配置通过 PowerShell 发送测试邮件,请参阅 使用 PowerShell 发送测试电子邮件。

检查数据库邮件系统参数

若要检查系统参数,请执行以下步骤:

  1. 打开 SSMS,选择“管理”,右键单击数据库邮件,然后选择“配置数据库邮件”。

  2. 选择“ 查看或更改系统参数”。

以下屏幕截图显示了系统参数的默认值。 请注意任何唯一的系统参数,并确定它们是否与要进行故障排除的问题有关。

在数据库邮件配置向导中配置系统参数的屏幕截图。

步骤 5:发送测试邮件

本部分介绍如何使用 SSMS 和 PowerShell 发送测试数据库邮件。

使用 数据库邮件 发送测试电子邮件

发送测试电子邮件有助于尝试重现所遇到的问题,并验证是否可以发送任何数据库邮件。

若要发送测试数据库邮件,请选择“管理”,右键单击数据库邮件,然后选择“发送测试电子邮件...”

右键单击数据库邮件后显示的“发送测试电子邮件”选项的屏幕截图。

发送测试邮件后,请检查数据库邮件日志和 sysmail 视图。

  • 如果未成功发送测试邮件,请使用本文档排查未发送邮件的原因。
  • 如果测试邮件已成功发送,但未发送的其他邮件仍存在问题,请关注未发送的电子邮件的详细信息。 查看正在执行的实际 sp_send_dbmail 命令。 如果没有 Transact-SQL 命令,请使用 sql_batch_completedsql_batch_started 命令收集 XEvent 跟踪并查看 batch_text 列。

使用 PowerShell 发送测试电子邮件

使用外部过程有助于排除故障排除中的数据库邮件并测试帐户配置。 例如,使用 PowerShell 发送测试邮件。 如果无法使用 PowerShell 发送测试邮件,则表明这不是数据库邮件问题。

如果从 PowerShell 发送的邮件失败并具有相同 SMTP 服务器设置和凭据,则可能表示问题位于 SMTP 服务器上。

  • 根据环境更改以下参数,然后运行以下脚本:

    $EmailFrom = "dbmail@contoso.com"
    $EmailPass = "Y0reP@ssw0rd"
    $EmailTo = "email_alias@contoso.com"
    $Port = 587
    $Subject = "Test From PowerShell"
    $Body = "Did this work?"
    $SMTPServer = "smtp.contoso.com"
    
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $Port)
    $SMTPClient.EnableSsl = $true
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom, $EmailPass);
    $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body) 
    
  • 如果 SMTP 服务器允许匿名身份验证,请使用标准端口 25,并且不需要 SSL。 运行以下脚本:

    $EmailFrom = "dbmail@contoso.com"
    $EmailTo = "email_alias@contoso.com"
    $Port = 25
    $Subject = "Test From PowerShell (Anonymous Auth, no SSL)"
    $Body = "Did this work?"
    $SMTPServer = "smtp.contoso.com"
    
    $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, $Port)
    $SMTPClient.EnableSsl = $true
    $SMTPClient.Credentials = New-Object System.Net.NetworkCredential($EmailFrom, $EmailPass);
    $SMTPClient.Send($EmailFrom, $EmailTo, $Subject, $Body) 
    

步骤 6:检查 sysmail Service Broker 对象

msdbService Broker 对象的问题可能会导致数据库邮件操作失败。 一个常见问题是,其中一个 Service Broker 队列(ExternalMailQueueInternalMailQueue)已禁用。 此问题可能是由无法在 Service Broker 中成功发送的病毒消息引起的。 例如,格式不正确的 XML。 如果五次尝试后无法发送消息,则被视为“病毒”,队列将被禁用,直到删除病毒消息。 重新启用队列无法解决问题,因为病毒消息仍在队列中,并且失败顺序只会重复。 有关病毒消息的详细信息,请参阅 病毒消息处理

另一个 Service Broker 对象(例如Message TypeContractServiceRoute)也可能被禁用或缺失。 Service Broker 队列具有与队列关联的激活过程,因此可能是故障点。 可以签入msdb.sys.service_queuesactivation_procedure,然后用于sp_helptext检查是否存在任何问题。

运行以下查询,然后检查查询结果的第二列的内容。

SELECT CONVERT(VARCHAR(32),name) Name, 'exec sp_helptext ''' + activation_procedure + '''' ActivationProc_Code 
FROM msdb.sys.service_queues

若要确定 Service Broker 对象是否存在任何问题,最好将对象与正常运行数据库邮件配置进行比较。 下面是应与以下对象进行比较的对象:

  • Message Types
    • {//www.microsoft.com/databasemail/messages}SendMail
    • {//www.microsoft.com/databasemail/messages}SendMailStatus
  • Contracts
    • www.microsoft.com/databasemail/contracts/SendMail/v1.0
  • Queues
    • dbo.ExternalMailQueue
    • dbo.InternalMailQueue
  • Services
    • ExternalMailService
    • InternalMailService
  • Routes

高级数据库邮件故障排除

高级故障排除适用于以下方案:

  • 查看数据库邮件日志时,数据库邮件崩溃,原因并未完全解释。 可以看到,启动 DatabaseMail 进程后立即出现异常消息,然后显示 DatabaseMail 进程正在关闭
  • 数据库邮件无法成功启动。 在视图中看不到 DatabaseMail 进程sysmail_event_log
  • 初始故障排除 无助于解决问题。

可以使用以下方法进行高级数据库邮件故障排除。

用于高级故障排除的集合

若要解决问题,可能需要一个或多个这些集合。

方法 1:备份 msdb 数据库

在独立于生产的环境中查询 sysmail 视图会很有帮助。 在某些情况下,可以备份 msdb 数据库,然后还原到另一个实例。 sysmail 视图都是使用对 msdb 的引用定义的,因此,即使查询还原 的 msdb 备份,视图也会引用 实例中的 msdb 系统数据库。 若要从生产 msdb 重新创建 sysmail 视图,请使用以下脚本在用户数据库中重新创建 sysmail 视图。

/* sysmail_allitems */

USE [msdb_customer]
GO

PRINT 'Creating view sysmail_allitems in msdb backup from customer...'
GO
IF (EXISTS (SELECT *
            FROM [msdb_customer].dbo.sysobjects
            WHERE (NAME = N'sysmail_allitems')
              AND (TYPE = 'V')))
  DROP VIEW sysmail_allitems
GO

CREATE VIEW sysmail_allitems
AS
SELECT mailitem_id, profile_id, recipients, copy_recipients, blind_copy_recipients, subject, body, body_format, importance, sensitivity, file_attachments,
       attachment_encoding, query, execute_query_database, attach_query_result_as_file, query_result_header, query_result_width, query_result_separator,
       exclude_query_output, append_query_error, send_request_date, send_request_user, sent_account_id,
       CASE sent_status 
          WHEN 0 THEN 'unsent' 
          WHEN 1 THEN 'sent' 
          WHEN 3 THEN 'retrying' 
          ELSE 'failed' 
       END AS sent_status,
       sent_date, last_mod_date, last_mod_user       
FROM [msdb_customer].dbo.sysmail_mailitems 
WHERE (send_request_user = SUSER_SNAME()) OR (ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) = 1) 

GO

/* sysmail_sentitems */

USE [msdb_customer]
GO

PRINT 'Creating view sysmail_sentitems in msdb backup from customer...'
GO
IF (EXISTS (SELECT *
            FROM [msdb_customer].dbo.sysobjects
            WHERE (NAME = N'sysmail_sentitems')
              AND (TYPE = 'V')))
  DROP VIEW sysmail_sentitems
GO

CREATE VIEW sysmail_sentitems
AS
SELECT * FROM [msdb_customer].dbo.sysmail_allitems WHERE sent_status = 'sent'

GO

/* sysmail_unsentitems */

USE [msdb_customer]
GO

PRINT 'Creating view sysmail_unsentitems in msdb backup from customer...'
GO
IF (EXISTS (SELECT *
            FROM [msdb_customer].dbo.sysobjects
            WHERE (NAME = N'sysmail_unsentitems')
              AND (TYPE = 'V')))
  DROP VIEW sysmail_unsentitems
GO

CREATE VIEW sysmail_unsentitems
AS
SELECT * FROM [msdb_customer].dbo.sysmail_allitems WHERE (sent_status = 'unsent' OR sent_status = 'retrying')

GO

/* sysmail_faileditems */

USE [msdb_customer]
GO

PRINT 'Creating view sysmail_faileditems in msdb backup from customer...'
GO
IF (EXISTS (SELECT *
            FROM [msdb_customer].dbo.sysobjects
            WHERE (NAME = N'sysmail_faileditems')
              AND (TYPE = 'V')))
  DROP VIEW sysmail_faileditems
GO

CREATE VIEW sysmail_faileditems
AS
SELECT * FROM [msdb_customer].dbo.sysmail_allitems WHERE sent_status = 'failed'

GO

/* sysmail_event_log */
USE [msdb_customer]
GO
PRINT 'Creating view sysmail_event_log in msdb backup from customer...'
GO
IF (EXISTS (SELECT *
            FROM [msdb_customer].dbo.sysobjects
            WHERE (NAME = N'sysmail_event_log')
              AND (TYPE = 'V')))
  DROP VIEW sysmail_event_log
GO
CREATE VIEW sysmail_event_log
AS
SELECT log_id,
       CASE event_type 
          WHEN 0 THEN 'success' 
          WHEN 1 THEN 'information' 
          WHEN 2 THEN 'warning' 
          ELSE 'error' 
       END as event_type,
       log_date, description, process_id, sl.mailitem_id, account_id, sl.last_mod_date, sl.last_mod_user
FROM [msdb_customer].[dbo].[sysmail_log]  sl
WHERE (ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) = 1) OR 
      (EXISTS ( SELECT mailitem_id FROM [msdb_customer].[dbo].[sysmail_allitems] ai WHERE sl.mailitem_id = ai.mailitem_id ))

GO

有关 sysmail 视图的详细信息,请参阅 sysmail 系统视图 部分。

方法 2:检查 Windows 应用程序事件日志

如果外部 DatabaseMail.exe 程序无法登录到 msdb 表,程序会将错误记录到 Windows 应用程序事件日志。 此外,如果 DatabaseMail.exe 遇到异常,也会记录异常。 尽管异常堆栈通常完全相同,但请检查事件日志以查看是否存在任何其他堆栈信息。

有时,排查 DatabaseMail.exe 崩溃问题时,你可能会发现日志记录指示已创建 Windows 错误报告转储,如下所示:

<datetime stamp>,Information,0,1001,Windows Error Reporting,Viewpoint.contoso.com,"Fault bucket , type 0
Event Name: APPCRASH
Response: Not available
Cab Id: 0
Problem signature:
P1: DatabaseMail.exe
P2: 11.0.2100.60
P3: 4f35e1a1
P4: KERNELBASE.dll
P5: 6.3.9600.18725
P6: 59380775
P7: c0000142
P8: 00000000000ece60
P9: 
P10: 
Attached files:
These files may be available here:
C:\ProgramData\Microsoft\Windows\WER\ReportQueue\AppCrash_DatabaseMail.exe_deaadc12935831f6bbfe9bdcb0cbf864374426c1_807e7507_337982fd
Analysis symbol: 
Rechecking for solution: 0
Report Id: <Report Id>
Report Status: 4100
Hashed bucket:"

可以检索在 .. 中 显示 AppCrash_DatabaseMail.exe_* 的所有文件。\WER\ReportQueue 路径。 有关转储分析建议,请参阅 ProcDump 分析部分。

方法 3:收集和分析 XEvent 或 SQL Server 跟踪

可以收集在系统上执行的 Transact-SQL 命令的跟踪,以查看其中任何命令是否失败。

配置 PSSDiag 工具

可以使用 PSSDiag 收集常规性能模板下的 XEvent 或 SQL Server 跟踪。 如以下屏幕截图所示,选择一些其他事件,尤其是所有中转站事件。

Pssdiag 工具的屏幕截图,其中启用了 XEvent 选项卡上的所有中转站事件。

分析 Xevent 或 SQL 跟踪

发送数据库邮件时,Xevent 或 Profiler 捕获中通常会看到五个不同的会话(SPID)。

  • sp_send_dbmail:运行 Transact-SQL 语句后,会看到用于将消息置于队列中的 ExternalMailQueue Service Broker 事件。

  • Service Broker 激活,用于通过DatabaseMail.exe将消息发送到 SMTP 服务器。 应用程序名称为“Microsoft SQL Server Service Broker 激活”。

  • 数据库邮件外部程序:这是从ExternalMailQueue队列接收消息并准备要发送到 SMTP 服务器的消息的外部数据库邮件程序。 应用程序名称为“DatabaseMail - DatabaseMail - ID<PID>”。

  • 数据库邮件外部程序:这是来自数据库邮件的另一个连接。 第一个连接处理队列中的 ExternalMailQueue 现有消息后,将创建连接以侦听要放置在队列中的其他消息。 如果队列中没有其他消息, DatabaseMail.exe 将终止并关闭此连接。

  • Service Broker 激活,用于通过DatabaseMail.exe从 SMTP 服务器接收响应消息。 它会更新 sysmail 表,以记录发送的邮件结果。

只能通过查看许多跟踪来了解预期行为。 了解差异的最佳方式是将跟踪与成功发送数据库邮件之一进行比较。 如果有时可以发送数据库邮件,请将跟踪与成功的跟踪进行比较,查看差异,并检查 SPID 报告的任何错误。 如果无法发送任何数据库邮件,请将跟踪与测试环境中成功发送的跟踪进行比较。

方法 4:捕获和分析进程监视器事件

进程监视器 (Procmon)是 Windows Sysinternals 套件的一部分。

进程监视器生成干扰捕获。 为了不错过任何内容,最好在捕获数据后(而不是在捕获过程中)应用筛选器。 通常,可以针对数据库邮件问题的重现来定位捕获,因此捕获的总体数据不会太大。

捕获文件、注册表、网络、进程和线程事件

开始 procmon.exe时,它会立即开始捕获数据。 GUI 非常简单。 需要停止事件捕获,直到准备好重现问题。 选择“文件>捕获事件”(Ctrl+E)取消选中菜单项并停止事件收集。 选择橡皮擦图标或按 Ctrl+X 清除已捕获的事件:

显示所有事件的 procmon 工具的屏幕截图。

准备好重现数据库邮件问题时,请执行以下步骤:

  1. 选择“文件>捕获事件”(Ctrl+E)开始捕获事件。
  2. 尝试发送数据库邮件以重现问题。
  3. 选择“文件>捕获事件”(Ctrl+E)以停止捕获事件。
  4. 将文件另存为 *。PML。

分析进程监视器跟踪

获得 .PML 文件,再次使用进程监视器打开该文件。 首先,将文件筛选到 DatabaseMail.exesqlservr.exe 进程。 然后,选择“ 筛选器 > ...” ,或单击筛选器图标以打开筛选器菜单。

对于 进程名称,请选择 sqlservr.exeDatabaseMail.exe,然后添加以下条目:

显示已筛选database.exe的 procmon 工具的屏幕截图。

正如 SQL XEvent 或 Trace 捕获的情况一样,它并不明显需要查找。 通常,启动分析的最佳方式是将跟踪与成功发送数据库邮件的 Procmon 捕获进行比较。 理想情况下,请将跟踪与从出现问题的同一环境中成功发送电子邮件进行比较。 但是,如果未在特定环境中成功发送数据库邮件,请将跟踪与其他环境中成功发送电子邮件进行比较。

DatabaseMail.exe 加载 DLL 或找不到 DatabaseMail.exe.config 文件时,分析非常有用。

方法 5:使用 ProcDump 工具收集和分析异常转储

ProcDump 也是 Windows Sysinternals 套件的一部分。

尝试捕获DatabaseMail.exe外部程序的内存转储时,ProcDump 非常有用。 通常,当DatabaseMail.exe遇到未经处理的异常时,可以使用 ProcDump 进行故障排除。

配置 ProcDump

若要配置 ProcDump 以在遇到未经处理的异常时捕获DatabaseMail.exe储,请先使用管理员权限打开命令提示符。 然后,使用以下命令启用 ProcDump 以捕获DatabaseMail.exe进程的转储

c:\Sysinternals> procdump -ma -t DatabaseMail.exe -w e2

命令窗口中会显示以下输出:

ProcDump v9.0 - Sysinternals process dump utility
Copyright (C) 2009-2017 Mark Russinovich and Andrew Richards
Sysinternals - www.sysinternals.com
 
Waiting for process named DatabaseMail.exe...

然后,重现问题。 将在执行ProcDump.exe的同一文件夹中创建转储。

分析异常转储

找到异常记录并检查导致异常的调用堆栈。

  1. 在 WinDbg 中打开转储文件(下载适用于 Windows 的调试工具 - WinDbg - Windows 驱动程序)。
  2. 使用 .ecxr!analyze -v 命令切换到异常记录。

有了堆栈后,开始搜索匹配调用堆栈的已知问题。 如果需要进一步的帮助,请联系 CSS 团队。

方法 6:使用时间旅行调试工具

时间旅行调试 (TTD) 捕获通常是困难问题的最后手段。 可以使用 WinDbg 预览版调试器 获取 。 有关 TTD 的综合说明和信息,请参阅 时间旅行调试 ,了解其工作原理以及如何进行分析。 如果达到这一点,则需要联系 CSS 团队。 但是,本部分提供了有关如何在必要时捕获 TTD 的说明。

配置 TTD

出于多种原因,DatabaseMail.exeTTD 捕获可能有点困难。 首先, DatabaseMail.exe 不会无限期地作为服务运行,但它由 SQL Server (sqlservr.exe) 进程调用。 因此,不能附加到它,但必须使用参数来配置 TTD-onLaunch,以在DatabaseMail.exe启动时开始捕获它。 其次,由于 DatabaseMail.exe 由另一个进程调用,因此 需要使用 Debug 子进程