排查数据库邮件问题

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

初始数据库邮件故障排除

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

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

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

Msdb sysmail 系统视图

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

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

    名称 类型 说明
    sysmail_allitems View Lists提交到数据库邮件的所有邮件。
    sysmail_event_log View Lists有关数据库邮件外部程序行为的消息。
    sysmail_faileditems View 有关数据库邮件无法发送的消息的信息。
    sysmail_mailattachments View 有关数据库邮件邮件附件的信息。
    sysmail_sentitems View 有关使用 数据库邮件 发送的消息的信息。
    sysmail_unsentitems View 有关数据库邮件当前正在尝试发送的消息的信息。
  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 可以具有以下值:

  • 错误
  • 警告
  • Information
  • 成功

若要仅显示所需的事件类型,请使用 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 table 是其他 sysmail 视图的基表。 视图 sysmail_allitems 基于表构建,是这些视图的超集。

注意

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

Sysmail_unsentitems

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

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

如果 msdb 中的 sysmail_unsentitems Service Broker 对象出现问题,还可以检查邮件。 ExternalMailQueue如果 或 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 对象

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

(、ContractServiceRoute) 等其他 Message TypeService Broker 对象之一也可能被禁用或丢失。 Service Broker 队列具有与队列关联的激活过程,因此可能是一个故障点。 可以在 中msdb.sys.service_queues检查activation_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 进程已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.exe ”和“DatabaseMail.exe”,然后添加以下条目:

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

与 SQL XEvent 或跟踪捕获一样,要查找的内容并不明显。 通常,开始分析的最佳方法是将跟踪与 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

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