7

Update 6 を参照してください。これには、問題を再現する方法を示す簡単なアプリがあります。

私は DTC の悪夢のような生活を送っています... 私たちの設定では、2 つのデータベースがあります。SQL Server 2008 データベースと Oracle データベース (11g だと思います)。オラクルのMTSがインストールされています。分散トランザクションを許可するように DTC を構成しました。Oracle テーブルへのすべてのアクセスは、リンク サーバーの Oracle テーブルに対して行われる SQL Server データベースのビューを介して行われます。

(DTC 構成に関して: チェック済み -> ネットワーク DTC アクセス、リモート クライアントの許可、インバウンドの許可、アウトバウンドの許可、相互認証 (3 つのオプションすべてを試行)、XA トランザクションの有効化、SNA LU 6.2 トランザクションの有効化。DTC は としてログインしますNT AUTHORITY\NetworkService)

このアプリは、多数の WCF サービスを呼び出してデータベース作業を実行する ASP.NET MVC 4.0 アプリです。現在、Web アプリと WCF サービスは同じアプリ プールを共有しています (関連性があるかどうかはわかりませんが、念のため...)。

当社のサービスには、トランザクション対応のものとそうでないものがあります。

トランザクション対応の各 WCF サービスには、そのインターフェイスに次の属性があります。

[ServiceContract(SessionMode=SessionMode.Required)]

インターフェイスのメソッド シグネチャの次の属性:

[TransactionFlow(TransactionFlowOption.Allowed)]

そして、すべてのメソッド実装で次の属性:

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]

私のデータ アクセス レイヤーでは、すべてのトランザクション メソッドが次のように設定されています。

using (IDbConnection conn = DbTools.GetConnection(_configStr, _connStr, true))
{
    using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
    {
        cmd.ExecuteNonQuery();
    }
    using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
    {
       ... Perform actual database work ...
    }
}

トランザクショナルなサービスは、トランザクショナル DAL コードを呼び出します。アイデアは、トランザクションである必要があるもの (いくつかのケース) を、トランザクションである必要のないもの (ケースの ~ 95%) から分離しておくことでした。

トランザクションおよび非トランザクションの WCF メソッドがトランザクション内から呼び出されることはあってはなりません (ただし、これは検証していませんが、これが問題の原因である可能性があります。よくわかりませんが、これが理由の一部です。ここで質問します。)

前述したように、ほとんどの場合、これで問題なく動作します。

定期的に、何がそれを開始したのか特定できず、エラーが発生し始めます。そして、それらが始まると、ほとんどすべてがしばらくの間失敗し始めます. 最終的に、物事は再び機能し始めます。理由はわかりません...これはすべて、単一ユーザーのテスト環境にあります。

時々、エラーは次のとおりです。

リンク サーバー "ORACLSERVERNAME" の OLE DB プロバイダ "OraOLEDB.Oracle" のネストされたトランザクションを開始できません。XACT_ABORT オプションが OFF に設定されていたため、ネストされたトランザクションが必要でした。

このメッセージは、トランザクション内に非トランザクションのものがあるときに発生していると思います.非XACT_ABORTトランザクションコードで設定していないためです(それで問題が解決する場合、それは完全に実行可能です)。

ただし、ほとんどの場合、エラーは次のとおりです。

System.Data.SqlClient.SqlException (0x80131904): リンク サーバー "ORACLSERVERNAME" の OLE DB プロバイダー "OraOLEDB.Oracle" が分散トランザクションを開始できなかったため、操作を実行できませんでした。

さて、当初は SQL Server テーブルでのみトランザクションを行っていましたが、すべて正常に機能していました。一部の Oracle テーブルにトランザクション サポートを追加してから、問題が発生し始めました。Oracleトランザクションが機能することは知っています。そして、私が言ったように、ほとんどの場合、すべてがただのハンキードーリーであり、それから時々失敗し始め、失敗をやめることを決定するまでしばらく失敗し続け、その後すべてが再び機能します.

それを「機能」としてユーザーに販売する方法を見つけたいと思っていますが、楽観的ではないので、追跡していただけると助かります。重要な情報が省略されている場合はお知らせください。

更新 1:トランザクションに DistributedIdentifier が設定されていないように見えることに気付いたので、次のEnsureDistributed()ブログ投稿からメソッドを追加しました: http://www.make-awesome.com/2010/04/forceively-creating-a-分散ネットトランザクション/

ハードコーディングされた Guid (多くの問題を引き起こすように思われる) の代わりに、トランザクションごとに新しい Guid を生成するようにしましたが、それは機能しているように見えますが、問題は解決していません。DistribuedIdentifier の欠如が他の根本的な問題を示しているかどうか疑問に思っています。私はこれまでにこのような環境を扱ったことがないので、何が「正常」なのかわかりません。

更新 2: DistributedIdentifier が WCF に渡されないことに気付きました。クライアントからは、Transaction.Current.TransactionInformation に DistributedIdentifier と LocalIdentifier があります。ただし、WCF サーバーには LocalIdentifier セットのみがあり、それはクライアント側とは異なる Guid です (これは理にかなっていますが、DistributedIdentifier が通過することを期待していました)。

更新 3:トランザクションが失敗している最中に、IIS をシャットダウンした後でも、DTC サービスをシャットダウンして再起動できないようです。たとえば、コンポーネント サービスに移動してセキュリティ設定を変更し、[適用] または [OK] をクリックすると、少し待ってから、「MS DTC サービスの再起動に失敗しました。詳細については、イベント ログを調べてください。 ."

イベントログでは、一連のイベントを取得します:

1 (from MSDTC): "The MS DTC service is stopping"
2 (From MSSQL$SQLEXPRESS): "The connection has been lost with Microsoft Distributed Transaction 
                            Coordinator (MS DTC). Recovery of any in-doubt distributed transactions 
                            involving Microsoft Distributed Transaction Coordinator (MS DTC) 
                            will begin once the connection is re-established. This is an 
                            informational message only. No user action is required."
-- Folowed by these 3 identical messages
3 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
4 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
5 (from MSDTC Client 2): 'MSDTC encountered an error (HR=0x80000171) while attempting to establish a secure connection with system GCOVA38.'
6 (From MSDTC 2): MSDTC started with the following settings:
                     Security Configuration (OFF = 0 and ON = 1):
                     Allow Remote Administrator = 0,
                     Network Clients = 1,
                     Trasaction Manager Communication: 
                     Allow Inbound Transactions = 1,
                     Allow Outbound Transactions = 1,
                     Transaction Internet Protocol (TIP) = 0,
                     Enable XA Transactions = 1,
                     Enable SNA LU 6.2 Transactions = 1,
                     MSDTC Communications Security = Mutual Authentication Required,
                     Account = NT AUTHORITY\NetworkService,
                     Firewall Exclusion Detected = 0
                     Transaction Bridge Installed = 0
                     Filtering Duplicate Events = 1

これは、どこかでトランザクションを開いたままにしている何かがあるのではないかと思いますか? より適切な用語がないため、コミットまたはロールバックされていない「ダングリング トランザクション」のようなものがあるように感じます。私が TransactionScope を使用する場合は常に、「using」ステートメントで発生しているため、すべてをロールバックまたはコミットする必要があります。しかし、私は本当にどういうわけか、何かが漏れていると思い始めています...

更新 4:更新 3 に関連します。手動で登録を行っています。接続文字列には「Enlist=false」があります。DBTools.GetConnection()現在のトランザクションを接続に参加させるかどうかを指定するブール値パラメーターを取ります。この更新を投稿しているのは、Update 3 の内容に基づいて、おそらく、トランザクションを参加させるはずのない接続が何らかの形で参加させているのではないかと考えているからです。

public static IDbConnection GetConnection(string configString, string connectionString, bool enlistTransaction)
{
    SqlConnection conn = new SqlConnection(connectionString);
    conn.Open();
    if (enlistTransaction && Transaction.Current != null)
    {
        conn.EnlistTransaction(Transaction.Current);
    }
    return conn;
}

public static IDbCommand GetCommand(IDbConnection conn, string command)
{
    IDbCommand cmd = conn.CreateCommand();
    cmd.CommandText = command;
    return cmd;
}

更新 5:グループを実行すると、同じテストの同じ場所で常に失敗する一連の単体テストを見つけることができました (ただし、そのテストを単独で何度も実行すると、失敗します)。失敗しないでください。これは、その前に実行されているテストと関係があります。) DTC トレース ログを取得することができました。最初に失敗したトランザクションを示すログを次に示します。成功したトランザクションが役立つ場合に備えて、以前のトランザクションもいくつか示しています。失敗したトランザクションは から始まりますseq=1846

pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.064   ;seq=1822       ;eventid=TRANSACTION_BEGUN                        ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.064   ;seq=1823       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '344d3060-811c-4fc6-bab6-0eea76e3af3a'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.064   ;seq=1824       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #2. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.064   ;seq=1825       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1005 enlisted as transaction enlistment #3. RM guid = '72efe9cc-80f2-4a5b-9659-28b07987b600'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.079   ;seq=1826       ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER    ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"received request to commit the transaction from beginner"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.079   ;seq=1827       ;eventid=RM_ISSUED_PREPARE                        ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"prepare request issued to resource manager #1004 for transaction enlistment #1"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.079   ;seq=1828       ;eventid=RM_ISSUED_PREPARE                        ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"prepare request issued to resource manager #1004 for transaction enlistment #2"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.079   ;seq=1829       ;eventid=RM_ISSUED_PREPARE                        ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"prepare request issued to resource manager #1005 for transaction enlistment #3"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1830       ;eventid=RM_VOTED_COMMIT                          ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 voted commit for transaction enlistment #2"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1831       ;eventid=RM_VOTED_COMMIT                          ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 voted commit for transaction enlistment #1"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1832       ;eventid=RM_VOTED_READ_ONLY                       ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"resource manager #1005 voted read-only for transaction enlistment #3"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1833       ;eventid=TRANSACTION_COMMITTED                    ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"transaction has got committed"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1834       ;eventid=RM_ISSUED_COMMIT                         ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"commit request issued to resource manager #1004 for transaction enlistment #1"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1835       ;eventid=RM_ISSUED_COMMIT                         ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"commit request issued to resource manager #1004 for transaction enlistment #2"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1836       ;eventid=RM_ACKNOWLEDGED_COMMIT                   ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of commit request from the resource manager #1004 for transaction enlistment #1"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.079   ;seq=1837       ;eventid=RM_ACKNOWLEDGED_COMMIT                   ;tx_guid=49a79b73-66c0-48cb-abb1-8b657a2e3e4d     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of commit request from the resource manager #1004 for transaction enlistment #2"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.002   ;seq=1838       ;eventid=TRANSACTION_BEGUN                        ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.018   ;seq=1839       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.018   ;seq=1840       ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER    ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6     ;"TM Identifier='(null)                                            '" ;"received request to commit the transaction from beginner"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:45.018   ;seq=1841       ;eventid=TRANSACTION_COMMITTED                    ;tx_guid=55dd8607-c01e-4135-a247-7ef435c70bc6     ;"TM Identifier='(null)                                            '" ;"transaction has got committed"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.106   ;seq=1842       ;eventid=TRANSACTION_BEGUN                        ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.121   ;seq=1843       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.121   ;seq=1844       ;eventid=RECEIVED_COMMIT_REQUEST_FROM_BEGINNER    ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7     ;"TM Identifier='(null)                                            '" ;"received request to commit the transaction from beginner"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:45.121   ;seq=1845       ;eventid=TRANSACTION_COMMITTED                    ;tx_guid=cc4a8215-3475-4c14-b40d-d150fc79f8f7     ;"TM Identifier='(null)                                            '" ;"transaction has got committed"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.657   ;seq=1846       ;eventid=TRANSACTION_BEGUN                        ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"transaction has begun, description :'<NULL>'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.657   ;seq=1847       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #1. RM guid = '344d3060-811c-4fc6-bab6-0eea76e3af3a'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1848       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"resource manager #1004 enlisted as transaction enlistment #2. RM guid = '7b16851c-00a5-41dd-b59c-b003dcae08ec'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1849       ;eventid=RM_ENLISTED_IN_TRANSACTION               ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"resource manager #1005 enlisted as transaction enlistment #3. RM guid = '72efe9cc-80f2-4a5b-9659-28b07987b600'"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1850       ;eventid=RECEIVED_ABORT_REQUEST_FROM_NON_BEGINNER ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"received request to abort the transaction from non beginner"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1851       ;eventid=TRANSACTION_ABORTING                     ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"transaction is aborting"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1852       ;eventid=RM_ISSUED_ABORT                          ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1004 for transaction enlistment #1"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1853       ;eventid=RM_ISSUED_ABORT                          ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1004 for transaction enlistment #2"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1854       ;eventid=RM_ISSUED_ABORT                          ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"abort request issued to resource manager #1005 for transaction enlistment #3"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1855       ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1005 for transaction enlistment #3"
pid=1244       ;tid=6284       ;time=10/15/2013-10:00:59.672   ;seq=1856       ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1004 for transaction enlistment #2"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:59.672   ;seq=1857       ;eventid=RM_ACKNOWLEDGED_ABORT                    ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"received acknowledgement of abort request from the resource manager #1004 for transaction enlistment #1"
pid=1244       ;tid=8488       ;time=10/15/2013-10:00:59.672   ;seq=1858       ;eventid=TRANSACTION_ABORTED                      ;tx_guid=d07cc436-033c-450b-a36c-7e2fe79cdb81     ;"TM Identifier='(null)                                            '" ;"transaction has been aborted"

よくわかりませんが、前のトランザクションの完了とこのトランザクションの開始の間に 14.5 秒の遅延があることに注意してください。単体テストがハングしているように見えますが、その理由はまだわかりません。

これはおそらく問題ではありませんが、失敗は以下の ExecuteNonQuery にあります。

public IClientInternal GetClient(string clientCode)
{
    string sql = "SELECT [CLIENT_CODE], [COMPANY], [EMPLOYEE] << more fields here >> FROM  OPENQUERY("+
                    _settings.LinkedOracleServer + ", 'SELECT * FROM CLIENT WHERE "+ 
                    "CLIENT_CODE = ''" + clientCode + "'' "+
                    "')";

    using (IDbConnection conn = DbTools.GetConnection(_configStr, _connStr, true))
    {
        using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
        {
            cmd.ExecuteNonQuery();
        }
        using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
        {
            DbTools.AddParameter(cmd, "@CLIENT_CODE", DbType.String, clientCode);
            IDataReader reader = cmd.ExecuteReader();
            if (reader.Read())
            {
                return ClientInternal.FromReaderRecord(reader);
            }
            return null;
        }
    }
}

このコードは、最終的に失敗する前に、何度も正常に呼び出されます。

私が疑問に思っているのは、オラクル側でトランザクションが適切にクリアされていない可能性があるかどうかです。私の理解が正しければ、Oracle には 10 個の分散トランザクション制限があります。以前の分散トランザクションがまだ開いていると考えられる可能性はありますか (これに関する兆候は見られません。すべての証拠は、以前のすべてのトランザクションが完全に動作していることを示しているようであり、DTC ログはそれらがコミットされていることを示しています)。

更新 6:かなり小さなコードで問題を発生させることができました。以下は、DB と clientCode の名前の変更を除いて、問題を再現するための正確なコードです。通話中です。何度も何度も電話SqlExceptionをかけることができますが、うまくいきます。私は何度も電話をかけることができ、それはうまくいきます。しかし、GetEmployeeBadges() を呼び出してからトランザクション内で呼び出すと、失敗します。これは、2 番目の呼び出しがトランザクションに参加した結果のようです。cmd.ExecuteReader()GetClients() The operation could not be performed because OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE" was unable to begin a distributed transaction.GetEmployeeBadges()GetClients()GetClients()

追加の注意として、GetEmployeeBadges(). これは私たちの環境のもう 1 つの奇妙な点ですが、V_EMPLOYEE と V_PAEMPLOYEE は実際にはさらに別の Oracle データベースのビューです。したがって、私が攻撃しているOracleサーバーには、別のOracleサーバーのビューがあります。これは、Oracle テーブルの Oracle ビューの SQL Server ビューです。私は知っています、それは少しナッツです。ここで機能するのは驚くべきことです。GetEmployeeBadges()をトランザクションで実行してトランザクションに参加させようとすると、実際には次のように失敗します。Cannot execute the query "<<query text here>>" against OLE DB provider "OraOLEDB.Oracle" for linked server "ORACLE".

これをさらに最小限にすることは想像できません。

class Program
{
    private static string connStr = @"Server=localhost\SQLEXPRESS;Database=MYDB;Trusted_Connection=True;Enlist=false";
    static void Main(string[] args)
    {
        GetEmployeeBadges();

        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 15, 0)))
        {
            GetClients();
            ts.Complete();
        }
    }

    private static void GetEmployeeBadges()
    {
        string sql = @"select * from OPENQUERY(ORACLE, 'select a.security_nbr, a.employee, b.last_name, b.first_name, b.department
                        from V_PAEMPLOYEE a, V_EMPLOYEE b
                        where 
                        LENGTH(TRIM(a.SECURITY_NBR)) > 0 and
                        a.EMPLOYEE = b.EMPLOYEE and
                        a.COMPANY = 3')";        
        using (IDbConnection conn = DbTools.GetConnection(connStr))
        {
            using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
            {
                cmd.ExecuteNonQuery();
            }
            using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
            {
                cmd.CommandTimeout = 240;
                IDataReader reader = cmd.ExecuteReader();
            }
        }
    }

    public static void GetClients()
    {
        string clientCode = "clientCode";
        string sql = @"SELECT [CLIENT_CODE], [COMPANY], [EMPLOYEE], [MENU_TOKEN_CODE], [ADMINISTRATOR_FLAG], [SUPERVISOR_FLAG], 
                              [CLIENT_DESCR], [DEFAULT_QUEUE_CODE], [FG_WHSE_CODE], [FRT_WHSE_CODE], [BILL_COMP_CODE], [FI_COMP_CODE], 
                              [DEFAULT_ROLE], [DEFAULT_PRINTER_CODE], [SHIP_PRINTER_CODE], [DEFAULT_DISPLAY] 
                       FROM  OPENQUERY( ORACLE, 'SELECT * FROM CLIENT WHERE CLIENT_CODE = ''clientCode''')";

        using (IDbConnection conn = DbTools.GetConnection(connStr, true))
        {
            using (IDbCommand cmd = DbTools.GetCommand(conn, "SET XACT_ABORT ON"))
            {
                cmd.ExecuteNonQuery();
            }
            using (IDbCommand cmd = DbTools.GetCommand(conn, sql))
            {
                DbTools.AddParameter(cmd, "@CLIENT_CODE", DbType.String, clientCode);
                IDataReader reader = cmd.ExecuteReader();
                reader.Read();
            }
        }
    }
}

役立つ場合に備えて、DbTools のものは次のとおりです。

public static class DbTools
{
    public static IDbConnection GetConnection(string connectionString)
    {
        return GetConnection(connectionString, false);
    }

    public static IDbConnection GetConnection(string connectionString, bool enlistTransaction)
    {
        SqlConnection conn = new SqlConnection(connectionString);
        conn.Open();
        if (enlistTransaction && Transaction.Current != null)
        {
            conn.EnlistTransaction(Transaction.Current);
        }
        return conn;
    }

    public static IDbCommand GetCommand(IDbConnection conn, string command)
    {
        IDbCommand cmd = conn.CreateCommand();
        cmd.CommandText = command;
        return cmd;
    }

    public static IDbDataParameter AddParameter(IDbCommand cmd, string name, DbType type, object value)
    {
        IDbDataParameter param = cmd.CreateParameter();
        param.ParameterName = name;
        param.DbType = type;
        param.Value = value != null ? value : DBNull.Value;
        cmd.Parameters.Add(param);
        return param;
    }
}

バウンティの残り時間はわずか 23 時間です。誰かにその150ポイントをあげたいです!!!

4

2 に答える 2

0

この問題は、非常に奇妙なセットアップが原因でした。

リンクされたOracleサーバーを持つSQLサーバーがあります。SQL Server で、Oracle サーバー上のテーブルに対するビューを作成します。Oracle サーバーには、さらに別の Oracle サーバーのテーブルのビューである少数のビューがあります。サーバー 2 の Oracle テーブルで、サーバー 1 の Oracle ビューの SQL サーバーでビューを作成しただけでした。ビューのビューからデータを取得するときにトランザクションを使用していなかったにもかかわらず、後続の実行でトランザクションが失敗していました。 (誰かがそれがどのように可能かについてコメントしたい場合は、説明が欲しいです。)

私たちの解決策は、単純に 2 つ目のリンク サーバーを作成し、ビューのビューをバイパスすることでした。なぜ最初からこれを行わなかったのか不思議に思われるかもしれませんが、それは単純に、この問題が発生するまで、2 つ目のリンク サーバーを用意する説得力のある理由がなかったからです (2 つ目のサーバーには非常に機密性の高い情報が含まれているため、アクセスするためのパスを最小限に抑えるというアイデアが気に入りました)。明らかに、今や説得力のある理由があります。

私は Exth3 に答えを与えませんでしたが、最終的に問題を見つけることにつながった情報を提供するための報奨金ポイントを彼/彼女に与えました。ありがとうExth3!

于 2013-10-17T12:45:13.840 に答える