DBの仕事は初心者なので、基本的な質問をお待ちください。ローカルコンピューターでSQL Server 2014を実行しています。さまざまなアプローチをテストするための小さなテーブルと基本的なクライアントアプリケーションがあります。 _INSERT INTO
_とUPDATE
ステートメントの両方で、テーブルロックのように見えるものを取得しています。クライアントは、次のコードを持つASP.NETアプリケーションです。
_OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();
_
このコードを実行してから、管理スタジオから_SELECT * FROM LAYOUTSv2
_を実行します。どちらの場合も、クライアントスレッドが一時停止しているとき(つまり、コミット/ロールバックの前)、SELECTクエリはコミット/ロールバックが発生するまでハングします。
テーブルには、主キーとして割り当てられたフィールドLAYOUTS_keyがあります。プロパティウィンドウでは、ページロックと行ロックの両方が許可されており、クラスター化されていることを示しています。テーブルのロックエスカレーション設定は無効です...私は、テーブルとAUTOの他の利用可能な設定の両方を変更せずに試しました。私はSELECT ... WITH (NOLOCK)
を試しましたが、すぐに結果が返されますが、十分注意してください here と他の場所では、私がやるべきことではありません。 ROWLOCK
とINSERT
ステートメントの両方にUPDATE
ヒントを付けようとしましたが、何も変更されていません。
私が探している動作は次のとおりです。INSERT
をコミットする前に、他のスレッドからのクエリは、INSERT
edされている行を除くすべての行を読み取ります。他のスレッドからのUPDATE
クエリをコミットする前に、UPDATE
edである行の開始バージョンを読み取ります。これを行う方法はありますか?ユースケースを明確にするために他の情報を提供する必要がある場合は、お知らせください。ありがとう。
「テーブル全体」をロックしていない可能性があります。
テーブルの行をロックしていますが、SELECT * FROM LAYOUTSv2
はテーブル全体を読み取ろうとするため、必ずそのロックによってブロックされます。
挿入の場合、READPAST
ヒントを指定して、ロックされた行をスキップすることができますが、UPDATE
の場合に希望の結果が得られません(行をスキップして再度読み取りません)行の開始バージョン)。
読み取りコミットスナップショット分離 のデータベースを構成する場合、これにより、両方のケースで望ましい効果が得られます(tempdb
の使用が増える代わりに)。
Insert文とupdate文は、行レベルのロックを作成することになっています。ただし、トランザクションのロック数が5,000以上の場合、ロックのエスカレーションが発生し、テーブルレベルのロックが作成されます。下記を参照してください。
https://technet.Microsoft.com/en-us/library/ms184286(v = sql.105).aspx