2017-08-17 317 views
2

ストアドプロシージャからログテーブルに書き込む必要があります。 このログ情報は、ロールバック・オフコースを乗り越えなければなりません。現在のトランザクション外でトランザクションをコミットします(Oracleの自律型トランザクションなど)

私はこの質問が以前に尋ねられたことは知っていますが、私の状況は異なり、私はこれらの質問で私の問題に対する答えを見つけることができません。

ストアドプロシージャにエラーがない場合は簡単ですが、ログテーブルのエントリはそこにあります。
複雑なものよりもエラーがある場合。
手順の中で、キャッチでロールバックを行い、データをログテーブルに挿入することができます。私はそれを知っており、すでにそれを行っています。
は、しかし、問題は、ストアドプロシージャは、次のように呼び出されたときです。

begin transaction 
exec myStoredProcedure 
rollback transaction 
select * from myLogTable 

私はそれがmimimal私の問題を示すために保たれ、このコードはあまり意味があります知っています。
ストアドプロシージャの呼び出し元がコミット/ロールバックを実行する場合、ストアドプロシージャでの処理は重要ではありません。私のログは常にロールバックされます。

私はログを記録したいデータを返す一時テーブルトリックを使用することはできません。呼び出し元が外部アプリケーションであるため、呼び出し元がロールバックを行った後にそのデータをログテーブルに挿入できるようにします私には源泉がありません。

ロギングは、1行のコードしか持たない別個の手順で実行されます。ログ・テーブルへの挿入です。
私が必要とするのは、現行のトランザクション外で、このプロシージャーで挿入をコミットする方法です。

これを行う方法はありますか?

ソリューション:

私はlad2025答えを使用して、これまでそれが問題やパフォーマンス上の問題もなく働いています。
しかし、この手順は毎日約1000回しか呼び出されませんが、あまり問題はないと思います。

答えて

2

それはそうのは、MSがそれに近づく方法をチェックしてみましょう非常に興味深いトピックです。

まずドキュメント:Migrating-Oracle-to-SQL-Server-2014-and-Azure-SQL-DB.pdf

ページ152

シミュレーションOracleの自律型トランザクションの

このセクションでは、SSMAは、Oracle V6.0のために自律型トランザクション (PRAGMA AUTONOMOUS_TRANSACTION)を処理する方法について説明します。あなたは自律型トランザクションとして( 手順、パッケージ・ファンクション、データベース・トリガーをパッケージ無名ブロック、プロシージャ、ファンクション、)PL/SQLブロックを定義する場合、これらの自律型トランザクションは は、マイクロソフトのSQL Serverの2014

で直接対応していません そのブロック内のDMLを呼び出し元のトランザクションコンテキストから分離します。ブロックは、 トランザクションと呼ばれる別のトランザクションによって開始された独立トランザクションである になります。

PL/SQLブロックを自律型トランザクションとしてマークするには、次の文を宣言セクションに含めます。 PRAGMA AUTONOMOUS_TRANSACTION;

SQL Server 2014では、自律型トランザクションはサポートされていません。トランザクションコンテキストから Transact-SQLブロックを分離する唯一の方法は、新しい接続を開くことです。

使用xp_ora2ms_exec2延長手続きや新しい トランザクションを開くために、SSMA 6.0拡張パックに同梱その拡張版 xp_ora2ms_exec2_ex、。このプロシージャの目的は、新しい 接続でストアド・プロシージャを起動し、関数本体内のストアド・プロシージャを起動することです。 SSMA for Oracle Extension Pack(Oracleの拡張機能Pack.7.5.0.msi用のみSSMA):

xp_ora2ms_exec2 
<active_spid> int, 
<login_time> datetime, 
<ms_db_name> varchar, 
<ms_schema_name> varchar, 
<ms_procedure_name> varchar, 
<bind_to_transaction_flag> varchar, 
[optional_parameters_for_procedure]; 

は、その後、あなたのサーバーのストアド・プロシージャや他のスクリプトにインストールする必要があります。 xp_ora2ms_exec2手順は、次の構文を持っています。

あなたのストアドプロシージャはなります:

CREATE TABLE myLogTable(i INT IDENTITY(1,1), 
         d DATETIME DEFAULT GETDATE(), 
         t NVARCHAR(1000)); 
GO 

CREATE OR ALTER PROCEDURE my_logging 
    @t NVARCHAR(MAX) 
AS 
BEGIN 
    INSERT INTO myLogTable(t) VALUES (@t); 
END; 
GO 

CREATE OR ALTER PROCEDURE myStoredProcedure 
AS 
BEGIN 
    -- some work 
    SELECT 1; 
    INSERT INTO myLogTable(t) 
    VALUES ('Standard logging that will perish after rollback'); 

    DECLARE @login_time DATETIME = GETDATE(); 
    DECLARE @custom_text_to_log NVARCHAR(100); 
    SET @custom_text_to_log=N'some custom loging that should survive rollback'; 
    DECLARE @database_name SYSNAME = DB_NAME(); 

    EXEC master.dbo.xp_ora2ms_exec2_ex 
     @@spid, 
     @login_time, 
     @database_name, 
     'dbo', 
     'my_logging', 
     'N', 
     @custom_text_to_log; 
END; 

と最終コール:

begin transaction 
exec myStoredProcedure 
rollback transaction 
select * from myLogTable; 

OUTPUT:

i d   t 
2 2017-08-21 some custom loging that should survive rollback 
+0

これは非常に興味深いようです。 DBをオフラインにせずにエクステンションパックをインストールできますか?それはパフォーマンスに影響しますか?後者は重要です。なぜなら、ロギングはオフコースで起こるからです。 – GuidoG

+0

@GuidoGのインストールは非常に簡単で、一連のスクリプトを実行します(マスターDBには多くのストアドプロシージャ/タイプがあります)。私はパフォーマンスをテストしません(私はDEV/QA envで試してみることをお勧めします)。多くのテストを行います。 – lad2025

+0

OKこれで感謝します – GuidoG

2

実際には、Autonomous transaction(Oracleのようなもの)を検索します。

1つの醜い方法は、ループバックリンクサーバーを使用することです。

警告:これはPoCです(私はPRODで使用する前に2回考えています)、多くのテストを行います。

DECLARE @servername SYSNAME; 
SET  @servername = CONVERT(SYSNAME, SERVERPROPERTY(N'ServerName')); 

EXECUTE sys.sp_addlinkedserver 
      @server = N'loopback', 
      @srvproduct = N'', 
      @provider = N'SQLNCLI', 
      @datasrc = @servername; 

EXECUTE sys.sp_serveroption 
      @server = N'loopback', 
      @optname = 'RPC OUT', 
      @optvalue = 'ON'; 

EXECUTE sys.sp_serveroption 
     @server = N'loopback', 
     @optname = 'remote proc transaction promotion', 
     @optvalue = 'OFF'; 

とコード:

DROP TABLE IF EXISTS myLogTable; 
CREATE TABLE myLogTable(i INT IDENTITY(1,1), 
         d DATETIME DEFAULT GETDATE(), 
         t NVARCHAR(1000)); 
GO 

CREATE OR ALTER PROCEDURE my_logging 
    @t NVARCHAR(MAX) 
AS 
BEGIN 
    INSERT INTO myLogTable(t) VALUES (@t); 
END; 
GO 

CREATE OR ALTER PROCEDURE myStoredProcedure 
AS 
BEGIN 
    -- some work 
    SELECT 1; 
    INSERT INTO myLogTable(t) 
    VALUES ('Standard logging that will perish after rollback'); 

    EXEC loopback.T1.dbo.my_logging 
     @t = N'some custom loging that should survive rollback'; 
END; 

FINAL CALL:

begin transaction 
exec myStoredProcedure 
rollback transaction 
select * from myLogTable 

出力:

i d   t 
2 2017-08-17 some custom loging that should survive rollback 
+0

はい自律型トランザクションは、私が探していますものです。私はすでにループバックリンクサーバーに関する記事を見つけましたが、頻繁に使用するとパフォーマンスの問題で使用することについて警告します – GuidoG

関連する問題