SQL 2008におけるSQL応用の-ブロッキング(Blocking)応用分析

4341 ワード

通常短い時間の渋滞は問題なく、忙しいアプリケーションが必要です。しかし、設計の悪いアプリケーションは、リソースをロックする必要がなく、他のセッションの読み込みと更新をブロックする長時間のブロックを引き起こす。
SQL Serverでは、閉塞プロセスは無期限にブロックを維持し、またはタイムアウトするまで(set lock kuによると、timeout)、サーバがクローズされ、プロセスが殺され、接続が完了しました。更新または他の元のトランザクションで発生した操作によって、リソース上のロックが解除されました。
長時間の渋滞の原因は以下の通りです。
1、インデックスのない表の過剰なラインロックはSQL Serverにロックをかけられ、他の仕事をブロックします。
2、アプリケーションは一つのトランザクションを開き、トランザクションが開かれている間、ユーザーにフィードバックまたはインタラクションを要求する。これは通常、GUIに最終ユーザにデータを入力させて、トランザクションを開いたままにするときに発生する。このとき、事務引用のどのリソースも占有される。
3、事務BEGIN後に照会したデータは、事務事務開始前に呼び出される可能性がある。
4、クエリが不適切にロックヒントを使用する。例えば、アプリケーションは少ない行しか使用しませんが、テーブルロックのヒントを使用します。
5、アプリケーションは長時間の運行の事務を使って、一つの事務で多くの行または多くの表を更新しました。(大量に更新した事務を複数の更新の少ない事務に変えて、合併性を改善するのに役立ちます。)
一、渋滞を見つけて解決する
SQL Serverを使った動的管理ビューのsys.dm_をデモします。オズwaitingtaskysは、初期のSQL Serverバージョンのシステム格納プロセスsp_に代わるブロックプロセスを見つける。who
渋滞の過程を見つけたら、sys.dm_を使います。exec_sqltext動的管理関数とsys.dm_exec_Connection(DMV)は実行中のクエリのSQLテキストを探し出し、強制的にプロセスを終了します。
強制終了プロセスは、キルコマンドを使います。キルルの使い方はMSDN:http://msdn.microsoft.com/zh-cn/library/ms173730.aspxを参照してください。
このコマンドには三つのパラメータがあります。
■セッションID    終了するプロセスのセッションID。session IDは、接続を確立する際にユーザ毎の接続に割り当てられる一意の整数(int)である。接続中に、セッションID値はこの接続にバンドルされる。接続が終了すると、整数値が解放され、新たな接続に割り当てられます。KILL session IDを使用して、指定されたセッションIDに関連する従来の非分散トランザクションおよび分散トランザクションを終了することができる。■UOW    分散型トランザクションを識別するワークユニット(UOW)ID。UOWはsys.dm_からできます。トレイlocksダイナミックマネジメントビューのrequest_ownerguid列で取得したGUID。エラーログから、またはMS DTCモニタでUOWを取得することもできます。分散式の監視に関する詳細は、MS DTCドキュメントを参照してください。KILL UOWを使用すると、孤立した分散型トランザクションが終了されます。これらのトランザクションは、仮想セッションID='−2'に関連付けられた任意のリアルセッションIDに関連付けられていない。表示を孤立させることができます。その方法は、sys.dm_を調べることです。トレイlocks、sys.dm_exec_sessionsまたはsys.dm_exec_requestsダイナミックマネジメントビューにおけるセッションID列。■WITH STATURSONLY    もっと早いKILL文でロールバックしている指定セッションIDまたはUOWの進捗報告を生成します。KILL WITH STATURSONLYは、現在のロールバックの進捗状況のみを表示します。
第1のクエリーウィンドウ:
 
BEGIN TRAN
UPDATE Production.ProductInventory
SET Quantity = 400
WHERE ProductID = 1 AND
LocationID = 1
第2のウィンドウ:
 
UPDATE Production.ProductInventory
SET Quantity = 406
WHERE ProductID = 1 AND
LocationID = 1
第3のウィンドウ:
 
SELECT blocking_session_id, wait_duration_ms, session_id
FROM sys.dm_os_waiting_tasks
WHERE blocking_session_id IS NOT NULL

/*
blocking_session_id wait_duration_ms session_id
52 23876 54
*/
SessionID 52のセッションがSessionID 54のセッションをブロックしていることが分かります。52は何をしていますか?第3のウィンドウで実行されます。
 
SELECT t.text
FROM sys.dm_exec_connections c
CROSS APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) t
WHERE c.session_id = 54

/*
text
(@1 int,@2 tinyint,@3 tinyint)UPDATE [Production].[ProductInventory] set [Quantity] = @1 WHERE
[ProductID]=@2 AND [LocationID]=@3
*/
は、最初のクエリーウィンドウの元SQL文ではなく、SQL Serverが自動パラメータ化計画キャッシュ(プリコンパイル)されています。私たちは強制的にセッションを終了します。第3のウィンドウで実行します。
 
kill 52
は、ウィンドウ1のステートメントとウィンドウ2のステートメントが終了します。
ヒント:三つ目の文の中で、sys.dm_を使います。exec_connections(DMV)はSession IDが53のmost_に戻った。recentsqlhandle列これはSQLテキストのメモリ内のポインタです。sys.dm_としてexec_sqltext動的管理関数の入力パラメータが使用されます。sys.dm_からexec_sqltextはtext列に戻り、列はブロックプロセスのSQLテキストを表示します。渋滞が列になると、ブロックキングを通過しなければなりません。session_idとsession_ID列は、元のブロックプロセスが発見されるまで、各ブロックプロセスを詳しく調べます。
二、設定文はロック解除待ちの時間が長いです。
イベントやステートメントがブロックされている場合、リソースのロックが解放されるのを待つことを意味します。私たちは事前にset lockを通過することができます。Timeoutは待ち時間を設定します。
文法は以下の通りです。SET LOCK_TIMEOUT time_period
パラメータはミリ秒単位です。オーバーするとロックエラーに戻ります。例:
第1のウィンドウで実行します。
 
USE AdventureWorks
BEGIN TRAN
UPDATE Production.ProductInventory
SET Quantity = 400
WHERE ProductID = 1 AND
LocationID = 1
は第2のウィンドウで実行します。
 
USE AdventureWorks
SET LOCK_TIMEOUT 1000
UPDATE Production.ProductInventory
SET Quantity = 406
WHERE ProductID = 1 AND
LocationID = 1

/*

Msg 1222, Level 16, State 51, Line 3
Lock request time out period exceeded.
The statement has been terminated.
*/
解析:この例では、ロックタイムアウト時間は1000ミリ秒、つまり1秒を設定しました。この設定はリソースがプロセスによって占有される時間に影響しません。他のプロセスのリリースを待つ時間に影響を与えます。