SQLServer排他制御に関する質問

このQ&Aのポイント
  • SQLServerにおける排他制御に関して質問です。トランザクション中に発生した問題について詳しく説明します。
  • トランザクション中に発生した問題について、SQLServerの排他制御について質問があります。詳細な事例とともに説明します。
  • SQLServerの排他制御に関する質問です。トランザクションが同時に実行された場合に起きた問題について解説します。
回答を見る
  • ベストアンサー

SQLServerにおける、排他制御に関して質問です。

SQLServerにおける、排他制御に関して質問です。 環境:  SQLサーバ  ・Windows 2003 Server SP2  ・SQL Server 2005 Standard Edition SP3  SQLクライアント  ・WindowsXP SP3  ・.NET Framework 3.5 SP1 VB.NET アプリ  DBアクセサ  ・ADO.NETを利用 ---------------------------------------------------------------------- 1.DBとのコネクションを確立        ・        ・        ・ 2.データベーストランザクションを開始(レベルはSerializable) 3.テーブルAに対してINSERTを実行   (テーブルAの主キーはオートインクリメント設定されている。) 4.3の結果、追加された主キーを取得するため、MAX()関数にて主キーの最大値(つまり、3で追加した行のはず)を取得 5.テーブルAを外部参照しているテーブルに対して、4で取得したテーブルAのキーを利用して、行を追加・更新などを行う。 6.コミットを行う。   (コネクションは、アプリケーションが終了するまで保持する・・・) ---------------------------------------------------------------------- この処理フローで実行していたシステムですが、 二つのクライアント(X,Y)から、同時に2からの処理が行われた際に排他されず、 Xが、Yが作成したレコードの主キー値を元に、5の更新を行ってしまいました。 ログを見ると、 2→成功 3→成功(別のレコードが作成された) 4→XがMAX関数にて、Yが作成したレコードの主キーを取得   ※処理そのものは成功しているが、論理的におかしい となっています。 論理的には、トランザクションをかけているので、3からの処理が同時に行われるはずはなく、 4で取得される番号も、それぞれが作成した行の主キー番号になるはずなのですが・・・。 論理的に見落としている点や、環境的な要因などで、考えられる原因はありますでしょうか・・・?

質問者が選んだベストアンサー

  • ベストアンサー
  • todo36
  • ベストアンサー率58% (728/1234)
回答No.1
IkaYakisoba
質問者

お礼

教えていただいた方法で問題が解決しました。 ありがとうございます。

関連するQ&A

  • 排他制御の仕方

    X_DBから条件取得し、Y_DBへデータを移し変える処理を画面PGで行っています。 (移し終わると、該当のレコードはX_DBから削除) この時、複数端末で同時に処理されると、X_DBの対象レコードが重複して選択されるため、排他処理を行いたいのですが、ORCLEでどの様な記述をしたらよいのでしょうか?

  • 排他制御について

    質問します。 VB.NETとSQLServer2000を使用して受発注処理を作成したいのですが、排他制御について今悩んでいます。 レコードロックの動作についてなのですが、Aさんが「A01」のデータをレコードロックでデータを画面に表示している場合に、Bさんも(別PCにて)同様にレコードロックで「A01」のデータを表示することは可能なのでしょうか?(取得できるのか) 何方かご教授お願い致します。

  • 排他ロックしたレコードが、別トランザクションから参照されてしまい困っています。

    SQL Server2000を使用し、 あるトランザクションで排他ロック(XLOCK)をかけたレコードが 他のトランザクションから共有ロックを使用し参照できてしまう状態は存在するのでしょうか? 排他ロックをかけたレコードが 他のトランザクションから参照できてしまい困っています。 現在、下記の環境で開発を行っております。 ・サーバ側 Windows Server2003 SQL Server2000(sp4) ・クライアント側 Windows Xp(sp3) jdk6.0 jdbc 3.0 Type4 以下が具体的な状況となります。 前提として、 ・二つのトランザクション(以下A、Bと表記します)が存在する。 ・AとBは別のユーザでコネクションを張っている。 ・autoCommitはfalseに設定している。 ・テーブルにプライマリキーやインデックスは張っていない。 ・レコードは10件。 ・分離レベルはREAD COMMITED (1)Aから、「SELECT * FROM TEST_TABLE WITH(XLOCK) 」を発行 (2)Bから、「SELECT * FROM TEST_TABLE」を発行 このような状況で、(1)、(2)の順で処理を行った場合に 私の認識では、(2)の検索時にタイムアウト等が発生するという認識です。 しかし、(2)のSQLは正常に終了し、(1)と同じデータが取得されてしまいます。 ◆その他、確認したこと ・(1)の処理直後に処理を停止し、Enterprise Managerでロックが取得されているか確認したところ、トランザクションAがすべてのレコードを排他ロック(X)していた。 ・(2)の処理直後にロックの状態を確認しても、やはりトランザクションAが、排他ロック(X)していた。 ・CSEを使いODBC経由で同様の操作を行った場合も同じ動作がおこる。 ・(1)WITH(XLOCK, TABLOCK)とすると(2)でデータが取得できなくなる。 ・(2)のSQLを「SELECT * FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定するとタイムアウトする(期待通りの動き) ・(2)のSQLを「SELECT COLUMN01 FROM TEST_TABLE WHERE COLUMN01 > 0」のように指定すると、今度は、なぜか取得出来てしまう。 ・(1)と(2)の間にトランザクションAでUPDATEなどを行うと(COMMITはしない)(2)のSQLのWHERE句や取得するカラムに関係なく、(2)のSQLはタイムアウトする(当り前か。。。) いろいろ書きましたが、排他ロックされたレコードに 共有ロックはかけれないという認識なのですが、 そうではないのでしょうか? また、そうではない場合どういった場合に、 共有ロックが可能となるのでしょうか? SQL Serverの排他制御に詳しい方や 同じような現象に陥った方がいましたら、ご教授お願いします。

  • VB+SQLserverでRecordCount問題

    こんばんわ。 VBでMSのSQLサーバに接続しデータをコピーするメンテナンスツールを作っています。 通常、レコードカウントを取得できますが、主キーが設定されていないテーブルの場合、RecordCountが「-1」になります。 このテーブルに主キーを設定しますとちゃんと取得します。 主キーが設定されていない状態で正確にRecordCountを取得する方法はないんでしょうか? 宜しくお願い致します。

  • 排他処理について

    VBでトランザクションをかけてあるテーブルを処理しています。 具体的にはテーブルAのレコードを一時的に別テーブル(テーブルB)に コピーしてそのレコードすべてを元のテーブルから削除して、 テーブルB内で処理をさせてから、そのデータをテーブルAに戻して コミットしています。 この処理中に、別PGもしくはSQLPlusでテーブルAからテーブルBに コピー対象の1レコードを削除してコミットしました。 これってエラーになる?ならない?それともトランザクション中だから テーブルAがコミットされて開放されるまで待ちの状態になる?? 実際どうなったかというとエラーにならなくて、その処理で最後に テーブルAにテーブルBをコピーしたときにエラーになって データがきえるという現象がおきてしまいました。 上記のような処理のときにOracle条ではどのような処理になるのでしょうか? よろしくお願いします。

  • Sqlserver2005でテーブルを作成してい分からなかったので質問

    Sqlserver2005でテーブルを作成してい分からなかったので質問します。 [テーブルA]  {フィールド1}主キー   (データ1000)   (データ1001)   (データ1002) これを親とするテーブルBを作成して [テーブルB]  {フィールド1}主キー{フィールド2}主キー  (データ1000)   (データ1001)  (データ1001)   (データ1002)  (データ1002)   (データ1003) [テーブルB]の{フィールド1と2}を[テーブルA]の {フィールド1}にリーレーションを張って [テーブルA]の{フィールド1}のデータが消した時に[テーブルB]の{フィールド1,2} のデータ、どちらかに該当するデータがあった場合に行ごと削除したいので {フィールド1,2}のリレーションシップの設定の「DeleteRule」を2つとも「重ねて表示」としたいのですが 「パスが循環するか、複数のパスに連鎖する可能性があります。ON DELETE NO ACTION、ON UPDATE NO ACTION、を指定するか、他の FOREIGN KEY 制約を変更してください。 制約を作成できませんでした。以前のエラーを調べてください。」 と表示されて出来ませんこの場合フィールド1,2どちらか1つのフィールドしか DeleteRule「重ねて表示」に設定できないのでしょうか? こういう風に分岐する道筋を明記するテーブルを作りたいのですが 1━┳2    ┗3   自分の作ったテーブルの構造が良くないかもしれないので上に書いてあるような テーブルでは駄目だという方もどういったテーブル構造が良いのか教えて欲しいです

  • トランザクションとlast_insert_id

    トランザクション中にinsertする予定のテーブル(未コミット)のauto_increment値を取得することはできるのでしょうか。 以下のような処理を期待しているのですが、hoge1テーブルのauto_increment値が取得できずに困っております。last_insert_id に関わらず、hoge1テーブルのauto_increment値が取得できる方法があれば教えてください。 (1) トランザクション開始 (2) $sql=" INSERT INTO hoge1(name) value('あああ'); "; (3) ( ロールバック ) (4) $key=mysql_insert_id(); (5) $sql2=" INSERT INTO hoge2(hoge1_primary,age) value($key,'20歳'); "; (6) ( ロールバック ) (7) コミット (8) トランザクション終了 よろしくお願いします。 環境: php5,mysql5 (InnoDB)

    • ベストアンサー
    • MySQL
  • SQLServer2005 デッドロックの解決方法

    デッドロックから抜け出せません。 原因が分からず困っています。 何かアドバイスをいただけないでしょうか? SQLServer2005でサービスパックは何も当ててません。 レコードが15万件ほどのテーブル1があります。 主キーは列A,B,C。 インデックスは主キーに対応したクラスタインデックスのみ。 他に列C,D,Eでも一意で、これを条件に更新を行います。 以下のUPDATE文が10個ほどの並列プロセスで流れている のですが、数百回に一度デッドロックが発生します。 条件のDとEの値は最低どちらかは異なり、確かに一意の レコードに対して更新をかけています。 UPDATE テーブル1 SET F = '1' WHERE C+D+E IN (SELECT TOP1 C+D+E FROM テーブル1 WHERE D = '値' AND E = '値' ORDER BY C) SQL Server Profilerでトレースしたところ、上記のUPDATE文 のみによって引き起こされているようです。 DeadLock Graphを見るとKEYではなくPAGEに対して更新ロック(U) を取り合う様が見れるのですが、ひどくぐちゃぐちゃです。 試しに条件文のSELECTのみWITH (ROWLOCK,UPDLOCK)でデバッグ してみたのですが、大量のPAGEロック(IU)と一つのKEYロック(U)が取得されます。 また、D,E,Cの順に一意の非クラスタ化インデックスを貼ると、すっきりするのですが PAGE(IU)とKEY(U)に2つずつロックされます。(どうして一つにならない?) そもそもUPDATE条件文の中のSELECT文は何ロックを取得するのでしょうか? 更新ロック(U)、それとも共有ロック(S)を取得してからの排他ロック(X)? よろしくお願いします。

  • SQLserver2000でプライマリーキーの設定でのエラー

    こんばんわ。 現在SQLの勉強をSQLserver2000でしているのですが、 SQL Enterprise Managerを使って、ある列に主キーを定義しようとして、鍵マークをつけて、保存しようとすると 以下のようなエラーがでて設定できません。 テーブル 'xxxxx' - インデックス 'PK_xxxxx' を作成できません。 ODBC エラー : [Microsoft][ODBC SQL Server Driver][SQL Server]インデックス ID 1 で重複したキーが見つかったので、CREATE UNIQUE INDEX は終了しました。もっとも重要な主キーは 'yyyyy ' です。 [Microsoft][ODBC SQL Server Driver][SQL Server]制約を作成できませんでした。以前のエラーを調べてください。 [Microsoft][ODBC SQL Server Driver][SQL Server]ステートメントは終了されました。 初心者なので、このエラーの意味するところが理解できません。 なにが間違っているのでしょうか。 よろしくお願いします。

  • Sqlトランザクションの必要性

    SQLServer2005Expressを使用しています。 そこでトランザクションについて質問させて頂きます。 複数のスレッドや複数の端末から1つのテーブルの1つのレコードを 更新する場合に、トランザクションを掛ける必要性はあるでしょうか。 複数のセットとなるテーブルを更新する場合はトランザクションで 整合性を保ちつつ排他を行うので必須と思いますが、 1つのテーブルの1つのレコードの場合も必須でしょうか。 また、必須ではなくてもトランザクションを掛けておく有効な理由は あるでしょうか。 ちなみにトランザクション中は、他のコネクションから参照も不可に なるようにしております。 よろしく願いいたします。