web-dev-qa-db-ja.com

DBテーブルでのSPIDの使用(テーブル変数の代わり)

予約に使用されるトランザクションデータベース...

私たちのベンダーは、#temptablesを@tablevariablesに置き換えるように依頼されました(コンパイルロックが重いため)。代わりに、SPIDを列として追加する実際のテーブルに置き換えて、ストアドプロシージャが適切な行でのみ機能するようにしました。

この操作方法にリスクはありますか?すべてのトランザクションが独自のトランザクション内に分離される前に...このテーブルを大量にロックしてしまうのではないかと心配していましたが、SQLは行レベルのロックを使用しているため、これ以上のロックは作成されません。

SQL Serverバージョン:2016 Enterprise-13.0.5216.0


CREATE TABLE dbo.qryTransactions (
    ID int IDENTITY (0,1) NOT NULL CONSTRAINT pk_qryTransactions PRIMARY KEY CLUSTERED,
    spid int NOT NULL,
    OrderID int,
    ItemID int,
    TimeTransactionStart datetime,
    TimeTransactionEnd datetime,
...other fields
    )

CREATE INDEX idx_qryTransactions_spidID ON qryTransactions (spid, ID) INCLUDE (ItemID, OrderID, TimeTransactionStart, TimeTransactionEnd)

8
outjet

コメントブロックに収まりきらないぐらい少しまとまりがあり、レイの回答に応じてOPが作成したコメントを強調したい場合:

  • 親プロシージャ(Common_InsertOrders_1)は一時テーブルを作成します
  • 子プロシージャ(InsertOrders)は一時テーブルをクエリします
  • 子プロシージャ(InsertOrders)のコンパイルロックが表示されている

1分間少し接していきます...このシナリオで何が起こるかについては、Sybase ASEです...

  • 各一時テーブルは一意のオブジェクトIDを取得します(確かに、オブジェクトIDはある時点で再利用できますが、これはまれであり、同時セッションでは発生しません)。
  • 一時テーブルのオブジェクトIDにchangeがあるため、Sybase ASEは通常、子プロシージャの実行ごとに強制的に再コンパイルします。
  • また、Sybase ASEは、ストアドプロシージャの呼び出し間で一時テーブルの構造が変更された(列の数が異なる、列名/データ型/ null可能性など)と判断した場合、子procを強制的に再コンパイルします。
  • より最近のバージョンのSybase ASEには、一時テーブルオブジェクトIDの変更を無視するように(事実上)コンパイラーに指示する構成があり、これにより子プロシージャの再コンパイルが不要になります(注:テーブル構造が変更された場合でも再コンパイルが行われます)。

OPの問題に戻ります(子プロシージャのコンパイルロック)...

  • sybase ASEの動作の痕跡がSQL Serverに残っている可能性はありますか(2つの製品がポッドにエンドウ豆があったときから)。
  • 子プロシージャの再コンパイルを削減(排除)できるSQL Server構成はありますか(オブジェクトIDの変更が原因の場合)?
  • oPは、親プロシージャが毎回まったく同じ構造/ DDLで一時テーブルを作成していることを確認できますか?

@@ SPIDで単一の永続テーブルを使用してセッション間で行を区別するという考えは...そこにあります... yuck;繰り返し発生する問題:

  • 孤立した行をクリーンアップする方法とタイミング
  • データベースエンジンが@@ SPIDを再利用すると、孤立したデータが存在する場合(または孤立したデータのクリーンアップ中に@@ SPID = 10が削除されるが、@で新しい/現在/アクティブなセッションがある場合など)、データの精度の問題が発生する可能性があります。 @ SPID = 10 =>クリーンアップが削除するデータが多すぎます)
  • 行ロックからページ/テーブルロックへのロックエスカレーションの可能性
  • テーブルにインデックスがある場合、インデックスを更新するときに潜在的な(b)ロック
  • テーブルが存在するデータベースに応じて、ログデバイスに書き込むためのより多くのアクティビティを確認している可能性があります(Sybase ASEでは、tempdbでのログ記録を効果的に無効にすることができます)。
  • 行レベル(排他的)のロックでさえ、他のセッションをブロックする可能性があります(分離レベルと、セッションが上記の排他的ロックをスキャンアンドペースト/スキップできるかどうかによって異なります)。

私は戻って根本的な問題(子プロシージャの再コンパイルロック)を(再)調査し、上記のコンパイルロックを削減(排除?)する方法があるかどうかを確認したいと思います。 [残念ながら、これらの問題に関する私のSQL Serverの知識は... NULL ...なので、SQL Serverコンパイラの専門家からの入力に興味があります。]

5
markp-fuso

@@SPIDをこのように使用すると、問題が発生するようです。

セッションIDは頻繁に再利用されます。ユーザー接続がログアウトするとすぐに、そのセッションIDは再び使用できるようになり、接続を試みる次のセッションで使用される可能性があります。

少なくともある程度の信頼性で機能させるには、同じ@@SPIDを持つテーブルから前の行を削除するログイントリガーが必要です。その場合、@@SPID列を使用してテーブルが大量にロックされる可能性があります。

SQL Serverは実際に行ロックを使用しますが、ページロックとテーブルロックも使用します。もちろん、適切なインデックス付けによってそれを軽減できるかもしれませんが、これは私にはまだアンチパターンのように見えます。

ストアドプロシージャが、影響を受けるテーブルへのアクセスに使用されるonlyメソッドである場合、sp_getapplockを介してアプリケーションロックを使用し、基本的にシリアル化することで調査できます。関連部品へのアクセス。 sp_getapplockのドキュメントは here です。 Erik Darling はそれについて興味深い投稿をしています here

8
Max Vernon

はい、リスクはあります。行ロックを使用してSQLを信頼するのは簡単です。たとえば、挿入と削除では少なくともページロックを使用すると確信しています。 SQLエンジンは、いくつかの要因に基づいてロックの種類を選択しますが、これらの要因には「自分の意見」は含まれません。一時テーブルをテーブル変数に変更するような包括的なソリューションは、一般的にも悪い考えです。テーブル変数は状況によっては非常に役立ちますが、制限とパフォーマンスの問題があります。私はほとんどの状況で一時テーブルを好みます。特に、テーブルが数十行を超える場合。システムに「重いコンパイルロック」が発生した理由と、それによってパフォーマンスがどのように低下​​したかをベンダーに説明する必要があります。あなたが見ているときはいつでも、あなたはある種の「重いロック」を見つけるでしょう。それは必ずしもロックが問題であることを意味しません。 @@ SPIDに関するMaxのコメントも重要です。さらに、トランザクションモデルとエラー処理は大きな問題になる可能性があります。システムでデッドロックまたは入力データ品質の問題が発生した場合、標準エラー処理により、qryTransactionsテーブルが適切にリセットされずにセッションが終了する可能性があります。 IMOは、元の問題に対する間違ったソリューションアプローチです。

4
Ray