SQL Serverのロック問題と解決方法

このQ&Aのポイント
  • SQL Serverでのタイムカード(打刻)システムにおいて、朝と夕方の打刻が重なるときにロック(クエリーのタイムアウト)が発生する問題があります。この問題を解決するための修正方法として、トランザクションをやめて参照時にNOLOCKを使用する方法があります。
  • 具体的には、社員マスタを更新する処理ではトランザクションを使用しており、この処理中に社員マスタ全体がロックされるため、他のプロセスからの同時アクセスが制限されます。一方、社員コードで指定したレコードのみを参照する処理では、NOLOCKを使用することでロックを回避できます。
  • ただし、トランザクションをやめることにより、データの整合性に関するリスクが生じます。そのため、トランザクションの必要性やデータの一貫性を考慮した上で、修正方法を選択する必要があります。また、他の影響も考慮する必要があります。
回答を見る
  • ベストアンサー

sql serverロックしてしまう

Aceess2010+sql server2012 expressでタイムカード(打刻)を20か所の営業所で利用しています。朝、夕方の打刻が重なる時にロック(クエリーでタイムアウト)が時々発生します。 ※画面から社員コードを入力して出勤などのボタンを押そうとするときに、社員マスタを読み込むときにクエリーでタイムアウトが発生します (1)社員1が退勤などを押して、社員マスタに更新する Set cn = CurrentProject.Connection cn.BeginTrans sql = "UPDATE TM_社員マスタ" sql = sql + " SET" sql = sql + " 打刻ボタン=9" sql = sql + " WHERE 社員コード='" & Me.社員コード & "'" cn.Execute sql cn.CommitTrans cn.Close Set cn = Nothing (2)社員2が退勤を押す前に自分の社員コードを入力(ここでクエリータイムアウトになる) sql = "SELECT * FROM TM_社員マスタ" sql = sql + " WHERE 社員コード='" & Me.社員コード & "'" rs.Open sql, cn If Not (rs.EOF And rs.BOF) Then Me.社員名 = rs!社員名 Me.雇用区分 = rs!雇用区分 (1)(2)の社員は別な社員で社員コードは違います ロックを発生させないための修正としては、(1)のトランザクショをやめて、(2)のSELECTでNOLOCKをつけて参照すれば良いのでしょうか? ちなみに、(1)でトランザクションをはずしてもUPDATE中は社員マスタ全体にロックがかかるのですか?それともWHEREで指定した社員コードのレコードだけロックがかかるですか? あまり、SQL SERVERが詳しくないのですが、宜しくお願いします

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

  • ベストアンサー
  • IDii24
  • ベストアンサー率24% (1597/6506)
回答No.1

このソースだとおそらくリンクテーブルを使っているのだと思います。リンクテーブルは読み込みの制御が出来ません。つまりAccessからNOLOCKなどを出してもSQLサーバーには届かないということです。リンクテーブルは近所のデーターを一緒に持ってきてAccessの中でクエリを掛けるので全員が同じことをすればロックは掛かります。 回避策はSet cn = CurrentProject.ConnectionをADOの接続に変更してTransactSQLで書き直すことです。 Dim CN As ADODB.Connection Set CN = New ADODB.Connection CN.Provider = "SQLOLEDB" CN.ConnectionString = "Persist Security Info=true;" & _ "Data Source=サーバー名;" & _ "Initial Catalog=XXDB;" & _ "User ID=XXXX;" & _ "Password=1234" CN.Open ’ この場合SQLの認証をドメインにしたほうが良いですけど、アプリケーションユーザーIDを作ってSQL認証でも構いません。推奨はされていませんが。

関連するQ&A

  • SQL Serverへの接続について

    すみませんが、どなたか教えてください。 Access2000のプロジェクトからADOを使って、OLE-DB経由でSQL Serverに接続しようとしています。 SQLステートメントを指定して、レコードセットを作成したいのですが、 以下のSQL分のテーブル名のSYARMに対して、オブジェクト名SYARMは無効ですというメッセージが出てきます。どこが問題になっているのでしょうか? Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset cn.Open "Provider=SQLOLEDB;" & "datasource=(local);" & "Integrated Security=SSPI;" rs.Open "SELECT * FROM SYARM WHERE KANNO=12345;", cn, adOpenKeyset, adLockOptimistic rs.Close cn.Close Set rs = Nothing Set cn = Nothing

  • SQL文を勉強し始めたのですが質問です。

    受講履歴表(研修コード、社員番号、評価)と、社員マスター(社員番号、氏名、部署番号)という2つの表があるときに、次の2つのSQL文はどちらでも同じでしょうか?それとも違う意味があるでしょうか? SELECT 社員マスター.社員番号, 研修コード, 評価, 氏名 FROM 受講履歴表, 社員マスター WHERE 受講履歴表.社員番号 = 社員マスター.社員番号 SELECT 受講履歴表.社員番号, 以下は上と同じ。 それから、もう一つ分からないのは、アクセスの講習を受けたときは、選択クエリを作るときは、多側のテーブルのフィールドを選んだのですが、SQLの教科書では、社員マスターのフィールドを選ぶように書いてありました。でも理由が書いていないので、なぜそうなのか、よくわかりません。 アクセスの選択クエリと、上のSQL文では、意味が違うのでしょうか?どなたかわかる方、教えていただければありがたいです。

  • sql server whereについて

    sql server express2012 のselect文で select * from 商品マスタ where 商品コード in (1,2,3,1)とした場合、商品マスタには商品コード=1のデータは1件しかないけど、商品コード=1のデータ(同一データ)を2行表示する方法はありませんか? 宜しくお願いします

  • ACCESS SQLで複数データ表示させるには?

    *************************************************** Private Sub Form_Load() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection mySQL = "select * from テーブル" rs.Open mySQL, cn, adOpenForwardOnly, adLockOptimistic ’コントロールに代入 Me.No = rs![No] Me.項目 = rs![項目] ・・・ End Sub *************************************************** こんな感じで、クエリでなくSQLで フォームにテーブルの全レコードを表示させたい場合、 どのようにすればよいのでしょうか? 上の文には、何が不足しているのでしょうか? http://www.accessclub.jp/ado/09.html を見ましたが、解決できませんでした。

  • エクセルからSQLサーバー 時間切れになるようになった

    cn.Open "Provider=SQLOLEDB;Data Source=NASTUN-PC\SQLEXPRESS; " & _ "Initial Catalog=" & サーバー名 & ";" & _ "Integrated Security=SSPI" cn.Execute "UPDATE Tbl SET チェック = 0" エクセルからSQLサーバーへ更新クエリを実行しています。 今までこのコードで問題なく作業できていたのですが 昨日から エラーNo:-2147217871 「時間切れになりました。」 というエラーになります。 cn.CommandTimeout = 120 と長くしても同じです。 何もいじってないのにできなくなるなんてあるのでしょうか? SQLサーバーにはテーブルのみおいています。 よろしくお願いします。

  • SQL文を教えて下さい

    VB2008、SQL Server で開発をしています。 下記の条件でデータを取得したいのですが、SQL文がうまくできず、困っています。 おわかりの方、教えてください。 仕様:得意先マスタ(得意先M)の全件と、売上テーブル(売上T)を読みます。     売上テーブルの商品コードの商品名を商品マスタ(商品M)より取得します。     得意先マスタの全得意先を取得する必要があります。     すべての得意先の売上データが存在するわけではありません。 ACCESS上でクエリを作成し、SQLビューにすると、こうなります。 inptSyoCD:画面から入力した商品コード 1,まず、クエリ1: SELECT 売上T.伝票日付, 売上T.伝票番号, 売上T.得意先コード, 売上T.明細区分, 売上T.商品コード, 商品M.商品名称 FROM 売上T LEFT JOIN 商品M 売上T.商品コード = 商品M.商品名 WHERE 売上T.明細区分=1 AND 売上T.商品コード= inptSyoCD ; 2,次に、実際に処理するSQL文: SELECT 得意先M.得意先コード, 得意先M.得意先名称,       クエリ1.伝票日付, クエリ1.伝票番号, クエリ1.明細区分, クエリ1.商品コード, クエリ1.商品名  FROM 得意先M LEFT JOIN クエリ1 ON 得意先M.得意先コード = クエリ1.得意先コード ORDER BY 得意先M.得意先コード,売上T.伝票日付,売上T.商品コード; この2つをひとつのSQL文にする方法がわかりません。 よろしくお願いいたします。

  • 排他的ロック

    もともとMicrosoft SQLで使用していたアプリケーションを多少改造し、MySQLにしようと思っています。 データ型もコマンドもすべて一致しているし、と思って構築をしていたら一つ見落としていたことがありました。 排他的ロックです。 MySQLで排他的ロックってどうやってやればいいのでしょう? ちなみに今はこのコマンドをどうすればMySQLで動くのか迷い中です。 SET LOCK_TIMEOUT 1000//ロックのタイムアウトを設定 SELECT * FROM # WITH(XLOCK) WHERE $//排他的ロック

    • ベストアンサー
    • MySQL
  • SQL文の最後に「;」はいらないのでしょうか?

    VBAのADOについて質問です。 SQL文の最後には「;」を付けなくちゃいけないものだと思っているのですが ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ Private Sub test_Click() Dim CN As ADODB.Connection Dim RS As ADODB.Recordset Set CN = CurrentProject.Connection Set RS = New ADODB.Recordset SQL = "SELECT * FROM Tテーブル" ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ でも問題なくコードが動きました。 SQL文の最後に「;」はいらないのでしょうか? ちなみに SQL = "SELECT * FROM Tテーブル;" でもエラーになりませんでした。

  • 他のPCのSQLサーバーに接続したい

    2台のPCはLANに繋がれていて、同じワークグループです。 PC1をサーバーとして PC2からPC1のSQLサーバーへ接続したいのですが どうすればいいのでしょうか? (エクセル→SQLサーバーです。) PC1は Dim cn As New ADODB.Connection cn.Open "Provider=SQLOLEDB;Data Source=○○○○\SQLEXPRESS; " & _ "Initial Catalog=" & サーバー名 & ";" & _ "Integrated Security=SSPI" rs.Open "Tテーブル", cn, adOpenStatic, adLockOptimistic と言うように接続しています。 PC2から同じようにコードを書いてみましたがやはりエラーになってしまいました。 多分、 「cn.Open "Provider=SQLOLEDB;Data Source=○○○○\SQLEXPRESS;」 の部分だと思うのですが どうすればPC2からPC1のSQLサーバーへ接続することができるのでしょうか? どちらも環境は OS:2000、オフィス:2003、 PC1のみSQLサーバー2005がインストールされています。 IPアドレスは固定です。 ご教授よろしくお願い致します。

  • ACCESS SQL実行後、条件入力用のテキストボックス値が消える

    ACCESSのフォームにテキストボックスでSQLの条件を入力し、 コマンドボタンを押して、そのSQLの結果をフォーム上に表示させています。 SQLの結果が表示される際に、条件となっていたテキストボックス値が消えてしまいます。 特に消すようなラインはいれていません。 条件はそのまま残したいのですが、なぜか消えてしまい、 その保存方法を教えていただきたいです。 (レコードが条件に1つも合致しない場合はテキストボックス値は 消えずにのこります。) ========================= mySQL = "SELECT register_name, PROJECT_NAME, sum(task_hours) as totalHours FROM Report WHERE register_name = '" & nameSearch & "' ←テキストボックス値条件 Group by PROJECT_NAME ;" RS.Open mySQL, cn, adOpenStatic, adLockReadOnly, CmdText If RS.RecordCount = 0 Then MsgBox "指定された条件に該当するレコードはありません", vbCritical, "警告" ELSE Me.empName.ControlSource = "register_name" Me.projName.ControlSource = "PROJECT_NAME" Me.projHours.ControlSource = "totalHours" Set Me.Recordset = RS END IF RS.Close: Set RS = Nothing cn.Close: Set cn = Nothing 以上です