2010-12-20 29 views
6

データベーステーブルに対してpl/sqlデベロッパーで単純なselectステートメントを実行すると、期待通りの標準的な結果セットが返されます。データベースビューから選択するだけで、オープンなトランザクションが得られるのはなぜですか?

最近、ビューから選択を行ったストアドプロシージャのクエリを貼り付け、トランザクションが一見開いたままになっていることに気付きました。これはロールバックによって評価され、PL/SQL開発者がコミットオプションを利用できました。

他の開発者のアンケートによると、これはPL/SQL開発者の設定が疑わしいものになることがあります。

なぜこの場合ですか? itelfビューには別のデータベースへのDBLinkがありますが、これは何の効果もないと思います。

どのような考えですか?

答えて

1

SQL文は、Oracleでトランザクションを開始します。

From the manual:

トランザクションは、最初の実行SQL文で始まります。トランザクションは、COMMITまたはROLLBACK文を使用して明示的に、またはDDL文が発行されたときに暗黙的にコミットまたはロールバックされると終了します。 [...] 実行 SQL文は、DMLとDDL文おそらくこれをseingされていない人たちは、自動コミットモードで実行されている

含めて、インスタンスへの呼び出しを生成するSQL文ですステートメントによって開始されたトランザクションは、ステートメントが終了した直後にコミットされます。データ操作言語(DML)文のクエリ

または既存のスキーマ・オブジェクト内のデータを操作:

その他SELECTがDMLではなく、再びthe manual clearly statesことを主張しています。 *取得または1つ以上の表またはビューからデータを取得(SELECT)
      *表またはビュー(INSERT)
[に新しいデータ行を追加し

     :彼らはすることができます。 ..]

+0

ありがとうございました。オートコミットモードはどのように切り替えられますか? –

+0

私はPL/SQL Developerを使用しないため、わかりません –

+5

@a_horse_with_no_name:すべてのSQL文がトランザクションを開始するとは限りません。私の(更新された)回答のデモンストレーションを見てください。 –

15

データベースのリンクがオープントランザクションのソースであるであると思われます。 PL/SQL Developerのリモート表でSELECT問合せを実行する前に、このような動作に気がつきました。トム・カイト(source)を引用する

分散型のものは、 "念のために" トランザクションを開始します。

EDIT: '任意のSQL文は、Oracleでトランザクションを開始'?いいえ、そうではありません。ここでそれを実証しています。このデモでは、アクティブ・トランザクションをリストするデータ・ディクショナリ・ビューV$TRANSACTIONを使用しています。これは、ローカルのOracle XEデータベース上で実行されています。このデータベースには、私以外のユーザーが接続されていません。

このデモンストレーションでは、次の表を使用します。これには単一の列のみが含まれます。

 
SQL> desc test; 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
A             NUMBER(38) 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

現時点ではアクティブな取引がありません。このテーブルに対してSQLクエリを実行しましょう:

 
SQL> select * from test; 

     A 
---------- 
     2 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

アクティブなトランザクションはまだありません。今度はトランザクションを開始する何かをしましょう:

期待どおり、今はアクティブなトランザクションがあります。

 
SQL> commit; 

Commit complete. 

SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

トランザクションをコミットした後は、もはやアクティブではありません。

ここで、データベースリンクを作成してみましょう。私は、Oracle XEを使用していますし、次は戻って自分自身に私のOracle XEインスタンスからのデータベース・リンクを作成します。

 
SQL> create database link loopback_xe connect to user identified by password using 'XE'; 

Database link created. 

は、今の私たちは、データベース・リンクを介してテーブルから選択したときに何が起こるか見てみましょう:

 
SQL> select count(*) from v$transaction; 

    COUNT(1) 
---------- 
     0 

SQL> select * from [email protected]_xe; 

     A 
---------- 
     2 
     1 

SQL> select count(*) from v$transaction; 

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

ご覧のとおり、リモートテーブルから選択するだけでトランザクションが開きます。

ここにコミットまたはロールバックするものが正確にはわかりませんが、その中にはおそらくその答えがある分散トランザクションの詳細を知りません。

+0

Oracleの概念マニュアルから:「トランザクションは最初の実行可能SQL文で開始します。トランザクションはコミットまたはロールバックされたときに終了します。 http://download.oracle.com/docs/cd/B28359_01/server.111/b28318/transact.htm#i1666 –

+0

あなたは正しいですが、ちょうど、v $ transactionからのクエリには注意が必要ですXEで一部のトランザクションは、そのビューには表示されません。たとえば、「set test = 0、1 = 2の更新」は、v $ transactionで行を作成するとは限りませんが、dbms_transaction.local_transaction_id()に表示されます。 –

+0

@Luke_Woodward Oracle内のdbリンクを介した問合せは、2フェーズ・コミットをサポートするためにトランザクションをオープンします。 DBA_2PC_PENDING表を問い合せて、リモートDB上の項目を表示することができます。 dbリンクを介してクエリを実行する場合、私はイニシエータがリモートDB上の副作用を知ることはできないと考えています。関数からクエリを実行している可能性があり、その関数がデータを変更する副作用を持つ可能性があります。私の経験(8iタイムフレーム):クエリーの後で、コミットまたはロールバックの前に起動したdbの障害は、トランザクションをリモートdbにオープンしたままにし、行をロックし、他のジョブに失敗しました。見つけて痛い。 – Glenn

1

通常のクエリでは、トランザクションを厳密に開くことはできません。データベースリンクを介して1つ開くことができます。医師へのリンクを掲示した人は意図的に、または全く不注意に2番目の文を削除した。

「最初の実行SQL文の に遭遇したときにOracle Databaseのトランザクションが開始されます。実行可能なSQL文は、DMLとDDL ステートメントを含むインスタンスへの呼び出しを生成し、SQL 文です。」

SELECTはDMLでもDDLでもありません。これを実際にテストするのはTRIVIALです。私はここでトロールのように降りたくはありませんが、人々はちょうどポイントを取得しようとするフォーラムで答えを投げ、答えは完全なゴミです本当に迷惑な。

残りのドキュメントを読んで、それをテストしてください。セッションへ

  • ログイン
  • あなたはv$transactionに(自分のセッション用)v$Sessionに参加して開かれたトランザクションを持っているかどうかを確認
  • 選択を実行します。

レコードが戻ってきたら、取引があります。そうでない場合、あなたはしません。

+2

"* SELECTはDMLでもDDLでもありません*"。このマニュアルは異なるものになります。http://docs.oracle.com/cd/B28359_01/server.111/b28318/sqlplsql.htm#autoId2「SELECT」は明確にDML文として分類されています。 –

+0

@a_horse_with_no_name申し訳ありませんが、11gのドキュメントでは、[SET TRANSACTION](http://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_10005.htm)で、 FOR UPDATE)はトランザクションを開始しません。そして、人々が実証しているように - そして、私は今、難しい道を学んだ - それは実際の行動のようです。 –

1

Oracle 11g Admin Guideによると、データベースリンクを介してプレーンな古いSELECTを実行すると、コミット(またはロールバック)する必要があるトランザクションが開始されます。

関連する問題