2009-08-19 24 views
25

現在のセッションでコミットされていないINSERT、UPDATE、またはDELETEステートメントがあるかどうかを調べる方法を探しています。 1つの方法は、現在のsidでv $ lockをチェックすることですが、これにはv $ lockへの読み取りアクセスが必要です。これはDBAが権限を与えたくない場合に問題になります。他の方法(アプリケーションによって発行されたすべてのデータベースコマンドを追跡する以外)Oracle:保留中のトランザクションがあるかどうかを調べる方法

+0

私はV $ビューにアクセスできないと思います。 – Gren

+0

[Oracleトランザクションでコミットされていない作業があるかどうかを確認するにはどうすればいいですか?](http://stackoverflow.com/questions/506456/how-can-i-tell-if-i-have-uncommitted-workオラクルのトランザクション) –

答えて

34

あなたのセッションがV$TRANSACTION内の行を持っているかどうかをチェックすることができます(もちろんそれは、このビューで読ま権限が必要):

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     0 

SQL> insert into a values (1); 

1 row inserted 

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     1 

SQL> commit; 

Commit complete 

SQL> SELECT COUNT(*) 
    2 FROM v$transaction t, v$session s, v$mystat m 
    3 WHERE t.ses_addr = s.saddr 
    4  AND s.sid = m.sid 
    5  AND ROWNUM = 1; 

    COUNT(*) 
---------- 
     0 
+0

この方法はうまくいかない場合があります。たとえば、データベースリンク(select * from remotetable @ databaselink)を使用してリモートデータベースからデータを選択するだけの場合、データを変更しなくてもトランザクションを開始します。この方法では、コミットされていないデータがあるとは限りません。 ...この種のトランザクションを除外するためにこのクエリを改善する方法はありますか?それは本当に私を困惑させる。 –

+0

@CarloSirnaはい、データを変更しなくてもOracleがトランザクションを開始するケースがあります。リモートデータベースへの接続の例があります(例えば、[Asktomのこのスレッド](https://asktom.oracle.com/pls/asktom/f?p=100:11:0:::P11_QUESTION_ID:8908307196113) )。単純な 'SELECT ...FOR UPDATE 'はまた、データを変更することなくトランザクションを開始する。私の答えに記載されているメソッドは、コミットされていないデータがある場合ではなく、保留中のトランザクションがあるかどうかを示します。 2つは同等ではありません(変更データで十分ですが、トランザクションの開始には必要ありません)。 –

21

これは私が通常使用しているクエリです

select s.sid 
     ,s.serial# 
     ,s.username 
     ,s.machine 
     ,s.status 
     ,s.lockwait 
     ,t.used_ublk 
     ,t.used_urec 
     ,t.start_time 
from v$transaction t 
inner join v$session s on t.addr = s.taddr; 
+1

は非常にうまく動作しますが、後でALTER SYSTEM KILL SESSION 'sid、serial#'で非アクティブなトランザクションを終了する必要があります。 – Diizzy

2

保留中のトランザクションについては、以下のクエリを使用してください。

値を返すと、保留中のトランザクションがあることを意味します。ここで

はクエリです:

select dbms_transaction.step_id from dual

参考文献:
http://www.acehints.com/2011/07/how-to-check-pending-transaction-in.html http://www.acehints.com/p/site-map.html

+0

SET TRANSACTIONを実行し、クエリを実行します。 –

0

マシュー・ワトソンは、RAC最も簡単で信頼性の高いソリューションを試してみて、トランザクションを開始し、それを見るためにある

select t.inst_id 
     ,s.sid 
     ,s.serial# 
     ,s.username 
     ,s.machine 
     ,s.status 
     ,s.lockwait 
     ,t.used_ublk 
     ,t.used_urec 
     ,t.start_time 
from gv$transaction t 
inner join gv$session s on t.addr = s.taddr; 
1

で使用されるように変更することができます 成功すれば一部のコードがすでにトランザクションを開始したが、まだDMLを発行していないコードがある場合、V $ TRANSACTIONビューには何も表示されません。

この例では、ユーザー定義のアプリケーションエラーを発生させるために例外を処理します。既存の例外ハンドラを延期するには、SET TRANSACTIONを実行してすぐにCOMMITを実行して元に戻します。

DECLARE 
    transaction_in_progress EXCEPTION; 
    PRAGMA EXCEPTION_INIT(transaction_in_progress, -1453); 
BEGIN 
    SET TRANSACTION NAME 'CHECK_FOR_TRANSACTION_ALREADY_SET'; 
    COMMIT; -- end transaction 
EXCEPTION 
    WHEN transaction_in_progress THEN 
     RAISE_APPLICATION_ERROR(-20000,'Transaction is already in progress'); 
END; 
/
関連する問題