読み取りクエリのトランザクションが必要ですか?
-
08-07-2019 - |
質問
私は、一部の開発者/ dbasが、すべてのデータベース呼び出し(読み取り専用呼び出しを含む)でトランザクションを使用することを推奨していることを読んでいます。トランザクション内での挿入/更新は理解していますが、トランザクション内で読み取ることの利点は何ですか?
解決
データベースの一貫したビューを取得します。相互にリンクする2つのテーブルがあるが、何らかの理由で2つの選択を行うと想像してください...疑似コードで:
myRows = query(SELECT * FROM A)
moreRows = query(SELECT * FROM B WHERE a_id IN myRows[id])
2つのクエリの間に誰かがBを変更していくつかの行を削除すると、問題が発生します。
他のヒント
RoBorgが言ったことと同様に、ステートメント間のファントムデータの読み取りを防ぐためにSELECT w / iトランザクションを実行します。 しかし SQL Serverのデフォルトのトランザクション分離レベルはREAD COMMITTEDであり、ダーティリードのみを防止することに注意することが重要です。ファントムデータを防ぐには、少なくともREPEATABLE READを使用する必要があります。 "このオプションは必要な場合にのみ使用してください。"
「トランザクション」の動作は、SQLサーバーごとに非常に異なることがわかりました。場合によっては、トランザクションがコミットまたはロールバックされるまで、トランザクションを開始すると他のすべての接続がロックされ、SQLを実行できなくなります(MS SQLServer 6.5)。その他には問題がなく、変更がある場合にのみロックします(oracle)。ロックは、セルロック/行ロック/ページロック/テーブルロックなどの変更のみを含むように拡張することもできます。
通常、複数の挿入/削除/更新ステートメント間のデータの整合性を維持する必要がある場合にのみトランザクションを使用します。それでも、データベース定義のカスケード削除を使用してこれを実装することで、データベースが自動的かつアトミックに実行できるようにします。
複数の変更をロールバックしたい状況を予測できる場合はトランザクションを使用しますが、それ以外の場合、データベースはそれを処理するための余分なコードなしでアトミック更新を行います。
これは私がもっと知っておくべきことなので、過去数分間これをチェックしてきました。ここに私が見つけたものがあります。
トランザクションは、人がレコードを読んでいるときにその行をロックし、変更したり読んだりしたくない場合にselectの周りで役立ちます。たとえば、次のクエリを実行します。
(クエリウィンドウ1内)
TRANの開始 SELECT * FROM MYTABLE WITH(ROWLOCK XLOCK) WHERE ID = 1
(クエリウィンドウ2内)
選択*マイテーブルから WHERE ID = 1
(クエリウィンドウ2は、ウィンドウ1でこれを実行するまで結果を返しません)
COMM TRAN
便利なリンク:
http://msdn.microsoft.com/en-us/library /aa213039.aspx
http://msdn.microsoft.com/en-us/library /aa213026.aspx
http://msdn.microsoft.com/en-us/library /ms190345.aspx
私の目標は、ブロックするものを取得することでした-そして、XLOCKをそこに追加した後、最終的に機能しました。 ROWLOCKを使用するだけでは機能しませんでした。私はそれが共有ロックを発行していたと仮定しています(そしてデータは読み込まれていました)..しかし私はまだこれを調査しています。
追加-WITH(UPDLOCK ROWLOCK)-行を選択して更新にロックすることができます。これは同時実行に役立ちます。
テーブルヒントに注意してください。それらを無計画に適用し始めた場合、アプリで少数のユーザーを取得しても、システムのクロールは遅くなります。これは私がこれを調べる前に知っていた1つのことです;)
トランザクションの主な目的の1つは、問題が発生した場合にロールバックの可能性を提供することです。