8

pl/sql 開発者でデータベース テーブルに対して単純な select ステートメントを実行すると、期待どおりに標準的な結果セットが返されます。

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

他の開発者を調査したところ、一部の開発者は影響を受けているようですが、他の開発者は影響を受けていないことが判明したため、PL/SQL Developer の設定を疑うようになりました。

いったいなぜ、このようなことになるのでしょうか? ビュー itelf には別のデータベースへの DBLink がありますが、これが何らかの効果をもたらすとは思いません。

何かご意見は?

4

6 に答える 6

20

予想に反して、データベース リンクオープン トランザクションのソースのようです。PL/SQL Developer でリモート テーブルに対して SELECT クエリを実行しているときに、このような動作に気付きました。

Tom Kyte を引用するには ( source ):

分散されたものは、「念のため」トランザクションを開始します。

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

このデモでは、次の表を使用します。1 つの列のみが含まれます。

SQL> デスクテスト;
 名前ヌル?タイプ
 ----------------------------------------- -------- - ---------------------------
 ナンバー(38)

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         0

現在アクティブなトランザクションはありません。このテーブルに対して SQL クエリを実行してみましょう。

SQL> select * from test;

         あ
----------
         2

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         0

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

SQL> テスト値に挿入 (1);

1 行が作成されました。

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         1

予想どおり、現在アクティブなトランザクションがあります。

SQL>コミット;

コミット完了。

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         0

トランザクションをコミットすると、アクティブではなくなります。

それでは、データベース リンクを作成しましょう。私は Oracle XE を使用しています。以下は、Oracle XE インスタンスからそれ自体へのデータベース リンクを作成します。

SQL> データベース リンクを作成する loopback_xe 'XE' を使用して、パスワードで識別されるユーザーに接続します。

データベース リンクが作成されました。

データベース リンクを介してテーブルから選択するとどうなるかを見てみましょう。

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         0

SQL> select * from test@loopback_xe;

         あ
----------
         2
         1

SQL> v$transaction から count(*) を選択します。

  カウント(1)
----------
         1

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

ここで何をコミットまたはロールバックする必要があるのか​​ 正確にはわかりませんが、分散トランザクションの内外を知らないことを認めなければなりません。おそらくその中に答えがあります。

于 2010-12-20T11:06:55.917 に答える
3

SQLステートメントは、Oracle でトランザクションを開始します。

マニュアルから:

トランザクションは、最初の実行可能な SQL ステートメントから始まります。トランザクションは、COMMIT または ROLLBACK ステートメントを使用して明示的に、または DDL ステートメントが発行されたときに暗黙的に、コミットまたはロールバックされると終了します。[...]実行可能な SQL ステートメントは、DML および DDL ステートメントを含む、インスタンスへの呼び出しを生成する SQL ステートメントです。

おそらく、これを見ていない人は、ステートメントによって開始されたトランザクションがステートメントの終了後すぐにコミットされる自動コミット モードで実行されている可能性があります。

SELECTaは DML ではないと主張する人もいますが、マニュアルには次のように明確に記載されています。

データ操作言語 (DML) ステートメントは、既存のスキーマ オブジェクト内のデータをクエリまたは操作します。

   * 1 つまたは複数のテーブルまたはビューからデータを取得またはフェッチする (SELECT) * 新しいデータ行をテーブルまたはビューに追加する
   (INSERT)
[...]
于 2010-12-20T10:55:20.390 に答える
1

通常のクエリで厳密にトランザクションを開くことは絶対にできません。データベース リンクから開くことができます。医師へのリンクを投稿した男は、故意に、またはまったく不注意に 2 番目の文を省略しました。

「Oracle Databaseのトランザクションは、最初の実行可能なSQL文が検出されたときに開始されます。実行可能なSQL文は、インスタンスへのコールを生成するSQL文であり、DMLおよびDDL文が含まれます。」

SELECT は DML でも DDL でもありません。これを実際にテストするのも簡単です。私はここで荒らしのようになりたくありませんが、人々がフォーラムで回答を投げ出してポイントを獲得しようとするだけで、回答が完全にゴミであると本当に面倒です.

ドキュメントの残りの部分を読み、最初にテストしてください。

  • セッションにログインする
  • 選択を実行する
  • v$Session(セッションで) に参加して、開いているトランザクションがあるかどうかを確認しますv$transaction

レコードが戻ってきたら、トランザクションがあります。そうでなければ、あなたはしません。

于 2012-04-04T16:02:09.260 に答える
0

TLDR:リモートデータベースから選択すると、リモートDBのセッションと接続も作成されます。そのセッションと接続は、ローカル ユーザー セッションの間持続します。ご想像のとおり、これにより、セッションと接続を維持する上でいくつかの問題が発生する可能性があります。

SO ALWAYS DO A COMMIT : SELECT * FROM emp@sales; 専念;

私は長い読書セクションが好きです:

これは、db_linksからの選択にトランザクションがあり、最終的にこれを終了することに決めた理由にも悩まされていたので、オラクルのドキュメントから:

Oracle® データベース管理者ガイド 11g リリース 2 (11.2) https://docs.oracle.com/html/E25494_01/ds_appdev002.htm

データベース リンクによって確立される接続の制御 グローバル オブジェクト名が SQL ステートメントまたはリモート プロシージャ コールで参照されると、データベース リンクは、ローカル ユーザーに代わってリモート データベース内のセッションへの接続を確立します。リモート接続とセッションは、ローカル ユーザー セッションの接続がまだ確立されていない場合にのみ作成されます。

リモート データベースに対して確立された接続とセッションは、アプリケーションまたはユーザーが明示的に終了しない限り、ローカル ユーザーのセッションの間持続します。データベース リンクを介して SELECT ステートメントを発行すると、元に戻すセグメントにトランザクション ロックがかかることに注意してください。セグメントを再解放するには、COMMIT または ROLLBACK ステートメントを発行する必要があります。

データベース リンクを使用して確立されたリモート接続を終了すると、アプリケーションで不要になった高コストの接続を切断するのに役立ちます。CLOSE DATABASE LINK 句を指定した ALTER SESSION 文を使用して、リモート接続とセッションを終了できます。たとえば、次のトランザクションを発行するとします。

SELECT * FROM emp@sales; 専念; 次のステートメントは、sales データベース リンクが指すリモート データベースのセッションを終了します。

ALTER SESSION CLOSE DATABASE LINK 販売; ユーザー セッションでデータベース リンク接続を閉じるには、ALTER SESSION システム権限が必要です。

注: データベース リンクを閉じる前に、まずそのリンクを使用するすべてのカーソルを閉じてから、リンクを使用している場合は現在のトランザクションを終了します。

ALTER SESSION 文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください

于 2020-05-27T11:35:36.803 に答える