次の方法で共有


データベース メールが SQL Server でメッセージを送信できない場合の 'トランザクションが無効です' エラー

この記事は、データベース メールがメッセージの送信に失敗する問題を解決するのに役立ちます。

元の製品バージョン: SQL Server 2012、SQL Server 2014、SQL Server 2016、SQL Server 2017 on Linux、SQL Server 2017 on Windows
元の KB 番号: 4502457

現象

Microsoft SQL Server を実行しているユーザーがデータベース メールを送信できないとします。 この状況では、データベース メール ログ (sysmail_event_log) に次のエントリが表示されます。

例外情報: 例外の種類: Microsoft.SqlServer.Management.SqlIMail.Server.Common.BaseException
メッセージ: トランザクションが無効です。
Data: System.Collections.ListDictionaryInternal
TargetSite: Void ValidateConnectionAndTransaction()
HelpLink: NULL
ソース: DatabaseMailEngine
StackTrace 情報:Microsoft.SqlServer.Management.SqlIMail.Server.DataAccess.ConnectionManager.ValidateConnectionAndTransaction() の
at Microsoft.SqlServer.Management.SqlIMail.Server.DataAccess.ConnectionManager.RollbackTransaction()
at Microsoft.SqlServer.Management.SqlIMail.IMailProcess.QueueItemProcesser.GetDataFromQueue(DataAccessAdapter da, Int32 lifetimeMinimumSec)
at Microsoft.SqlServer.Management.SqlIMail.IMailProcess.QueueItemProcesser.ProcessQueueItems(String dbName, String dbServerName, Int32 lifetimeMinimumSec, LogLevel loggingLevel, Byte[] encryptionKey, Int32 connectionTimeout)',@proc

Note

  • この語句有効ではなくなりますトランザクションが無効であることを意味するためMessage フィールドにこの方法で表示されます
  • アプリケーション ログに同じメッセージが表示される場合があります。 メール メッセージは sysmail_unsentitemsの "再試行" 状態のままであり、DatabaseMail.exe外部プログラムが正常に実行されるまで、未送信のままになります。

原因

SQL Server の既定の接続オプションでは、 SET NUMERIC_ARITHABORT ON が使用されます。 sp_send_dbmailを実行すると、メール メッセージは ExternalMailQueue にキューに入れられます。 メッセージがキューに表示されると、アクティブ化ストアド プロシージャによって外部実行可能ファイルDatabaseMail.exeがトリガーされます。 DatabaseMail.exeが SQL Server に接続されると、キューからメッセージを読み取るためにsp_readrequest実行されます。 sp_readrequestの実行中に、例外が発生する場合があります。 次の SELECT ステートメントは、 sp_readrequest で実行されます (この SELECT ステートメントを表示するには、ステートメント レベルのトレースを収集する必要があります)。

DatabaseMail - DatabaseMail - Id\<ProcessId>        \<NTUserName>        \<SPID>                \<StartTime>              msdb        \<LoginSid>  \<SessionLoginName>
-- network protocol: TCP/IP
set quoted_identifier on
set arithabort off
set numeric_roundabort on
set ansi_warnings on
set ansi_padding on
set ansi_nulls on
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
2 - Pooled        1        1 - Non-DAC
RPC:Starting <BinaryData> 4 <NTUserName> DatabaseMail - DatabaseMail - Id<ProcessId> <NTUserName> <SPID> <StartTime> sp_readrequest msdb <LoginSid> <SessionLoginName> exec sp_readrequest @receive_timeout=600000

SP:StmtStarting <BinaryData> 4 <NTUserName> DatabaseMail - DatabaseMail - Id<ProcessId> <NTUserName> <SPID> <StartTime> sp_readrequest msdb <LoginSid> <SessionLoginName>

SELECT @mailitem_id = MailRequest.Properties.value('(MailItemId)[1]', 'int')  
FROM @xmlblob.nodes('
declare namespace requests="https://schemas.microsoft.com/databasemail/requests]";/requests:SendMail')

AS MailRequest(Properties)
If SET NUMERIC_ARITHABORT ON is set as default connection option, this SELECT statement will encounter error 1934 and an exception will occur:

Exception 4 <servername> DatabaseMail - DatabaseMail - Id<ProcessId> <NTUserName> <SPID> <StartTime> 1934 msdb <LoginSid> <SessionLoginName> SELECT failed because the following SET options have incorrect settings:  
'NUMERIC_ROUNDABORT'.  
Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatialindex operations.

DatabaseMail.exe例外が発生すると、ロールバックは試行されますが失敗します。 この例外により、トランザクションがスコープ外になります。 このため、transaction は有効ではなくなりましたメッセージはデータベース メール ログに記録されます。

ただし、この問題の根本原因は、XML データ型メソッド (MailRequest.Properties.value('(MailItemId)[1]', 'int')) が SELECT ステートメントで使用されている場合に、互換性のない SET オプションが原因でエラー 1934 が発生することです。

エラー メッセージを確認する

  • データベース メール ログ内のエラー メッセージが同じメッセージであるかどうかを確認します (トランザクションは無効です)。

  • ステートメント レベルのイベント、エラーと警告、ブローカー イベントを有効にして、プロファイラー トレースを収集します。

  • 既定の接続オプションについては、SQL Server インスタンスの設定を確認します。 これを行うには、 SQL Server Management Studioを開き、 Server を右クリックし、 Properties>Connections>Default 接続オプション>数値のラウンド 中止を選択します。

解決方法

この問題を解決するには、既定の接続オプションを SET NUMERIC_ROUNDABORT OFF に変更します。