49

私はSQLServer2000を使用しており、SQLServer2000のストアドプロシージャの多くは一時テーブルを広範囲に使用しています。データベースには大量のトラフィックがあり、一時テーブルの作成と削除のスレッドセーフが心配です。

いくつかの一時テーブルを作成するストアドプロシージャがあり、一時テーブルを他の一時テーブルに結合することもできます。また、2人のユーザーが同時にストアドプロシージャを実行するとします。

  • 1人のユーザーがspを実行し、#tempという一時テーブルを作成し、別のユーザーが同じspを実行しても、#tempというテーブルがデータベースにすでに存在するために停止する可能性はありますか?

  • 同じユーザーが同じ接続で同じストアドプロシージャを2回実行した場合はどうでしょうか。

  • 2人のユーザーのクエリが互いに干渉する可能性のある他の奇妙なシナリオはありますか?

4

9 に答える 9

38

最初のケースでは、いいえ、できません。#tempはローカルの一時テーブルであり、他の接続には表示されないためです(ユーザーが個別のデータベース接続を使用していると想定されます)。一時テーブル名は、生成されたランダムな名前にエイリアスされ、ローカルの一時テーブルを参照するときにそれを参照します。

この場合、ストアドプロシージャでローカル一時テーブルを作成しているため、プロシージャのスコープが終了すると、その一時テーブルは削除されます(「備考」セクションを参照)。

ストアドプロシージャで作成されたローカル一時テーブルは、ストアドプロシージャが完了すると自動的に削除されます。テーブルは、テーブルを作成したストアドプロシージャによって実行されるネストされたストアドプロシージャから参照できます。テーブルを作成したストアドプロシージャを呼び出したプロセスがテーブルを参照することはできません。

2番目のケースでは、はい、テーブルがすでに存在し、接続が存在する限りテーブルが存続するため、このエラーが発生します。その場合は、テーブルを作成する前に、テーブルの存在を確認することをお勧めします。

于 2009-01-21T20:59:05.223 に答える
9

ローカルスコープの一時テーブル(単一の#)は、それらを一意にする識別子を最後に付けて作成されます。複数の発信者(同じログインでも)が重複してはなりません。

(試してみてください:2つの接続と同じログインから同じ一時テーブルを作成します。次に、tempdb.dbo.sysobjectsにクエリを実行して、作成された実際のテーブルを確認します...)

于 2009-01-21T21:00:23.613 に答える
5

ローカル一時テーブルは、現在のコンテキスト内にのみ存在するため、スレッド セーフです。コンテキストを現在の接続と混同しないでください ( MSDNから:「ストアド プロシージャで作成されたローカル一時テーブルは、ストアド プロシージャが終了すると自動的に削除されます」)。同じ接続で、作成するストアド プロシージャを 2 回以上安全に呼び出すことができます。ローカル一時テーブル ( など#TMP)。

この動作をテストするには、2 つの接続から次のストアド プロシージャを実行します。この SP は 30 秒間待機するため、2 つのスレッドがそれぞれのバージョンの #TMP テーブルで同時に実行されていることを確認できます。

CREATE PROCEDURE myProc(@n INT)
AS BEGIN
    RAISERROR('running with (%d)', 0, 1, @n);
    CREATE TABLE #TMP(n INT);
    INSERT #TMP VALUES(@n);
    INSERT #TMP VALUES(@n * 10);
    INSERT #TMP VALUES(@n * 100);
    WAITFOR DELAY '00:00:30';
    SELECT * FROM #TMP;
END;
于 2012-05-08T18:20:06.510 に答える
3

一時テーブルはセッションに関連付けられているため、異なるユーザーがプロシージャを同時に実行しても、競合は発生しません...

于 2009-01-21T20:56:34.247 に答える
2

一時テーブルは、それらを作成するクエリまたはプロシージャのコンテキストでのみ作成されます。新しいクエリはそれぞれ、他のクエリの一時テーブルがないデータベース上のコンテキストを取得します。そのため、名前の衝突は問題ではありません。

于 2009-01-21T20:57:10.157 に答える
1

tempsデータベースを見ると、そこに一時テーブルがあり、システムによって生成された名前が付けられています。したがって、通常のデッドロック以外は問題ありません。

于 2009-01-21T20:58:14.790 に答える
0

シャープ記号 ##temp を 2 つ使用しない限り、一時テーブルはローカルになり、ユーザーへのローカル接続用にのみ存在します。

于 2009-01-21T21:03:14.513 に答える
0

最初に、実際の一時テーブルを使用していることを確認しましょう。それらは # または ## で始まっていますか? その場で実際のテーブルを作成し、それらを繰り返し削除して再作成する場合、実際に同時ユーザーに問題が発生します。グローバル一時テーブル (## で始まるテーブル) を作成している場合も、問題が発生する可能性があります。同時実行の問題が発生しないようにする場合は、ローカル一時テーブルを使用します (# で始まります)。また、proc の最後 (または、長いマルチステップ proc について話している場合は、proc で不要になったとき) にそれらを明示的に閉じ、作成する前に存在を確認する (存在する場合は削除する) こともお勧めします。 .

于 2009-01-21T21:17:31.567 に答える