NOLOCKでADO.NET TransactionScopeとExecuteCommandを使用する大容量サイト、直接UNCOMMITTEDを読み取りますか?
-
06-07-2019 - |
質問
Omarのブログでこの興味深い記事を読んでください Linq to SQLは、コミットされていない読み取りを使用してトランザクションのデッドロックとクエリタイムアウトの問題を解決しますおよび最後に Javed Hasanは、大量のサイトでのnolock状況に対する彼の解決策について彼と議論し始めました。
ここで解決しようとしている問題は、SQLの意味から、NOLOCKでSelectステートメントを使用するか、SET TRANSACTION LEVEL READ UNCOMMITTEDを使用する必要があることです。そうしないと、DBの大容量行でロックされ、エラーが発生します。 Omarが使用するテクノロジーはLinq2Sqlであるため、問題はC#データアクセスコードでこれをどのように達成して上記が起こらないようにするかです。
基本的に、Omarは現実世界のサイトとSqlProfilerなどのツールで作業およびテストすることでソリューションを実現しますが、Javed HasanはMSDNドキュメントやScott Hanselmanのブログ投稿などでソリューションを実現します。
Omarは次の使用を推奨しています
using (var db = new DropthingsDataContext2())
{
db.Connection.Open();
db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var user = db.aspnet_Users.First();
var pages = user.Pages.ToList();
}
一方、Javed Hasanが提案する
using (new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
//Your db Operation
}
StatckOverflowのような大規模なサイトでこの特定の問題について皆さんが何をしているのか、あるいはジェフとその仲間たちがこの点で何をしたのかを知りたいですか?
編集:最初の投稿を読んだ後、Omarの投稿でいくつかの点を指摘します。
- 彼はアプローチで接続の問題に遭遇しましたが、彼はそれを解決しました。彼の投稿を参照してください。
- さらに重要なこととして、彼はADO.NET Transactionの使用方法を試し、Scott Hanselmanが彼のブログで書いたことを試したと述べましたが、それは大容量サイトでは機能せず、パフォーマンスをかなり低下させます。 Omarは、この" System.Transactionsにはかなりのオーバーヘッドがあると述べました。 CPUを100%にせず、Req / secを1/10に下げることなく、大量のWebサイトで使用することはできませんでした。大量のWebサイト用ではなく、エンタープライズアプリケーション用に作成されています。"
解決
まず、コミットされていない読み取りは避けてください。多くの問題が発生する可能性があります。より良いアプローチは、データベースを snapshot isolation <に設定することです。 / a>。 これはジェフがしたことです。
ジェフは基本的に次のように述べています:「bla bla bla、be real、bla bla bla、データベース理論家、bla bla bla、READ UNCOMMITTEDは、データの一貫性を必要としない実際の本番アプリに役立ちます」ジェフはDBAではありません。幸い、SOには多くのDBAがいます。
Omarのアプローチの問題は、「コミットされていない読み取り」で接続がリークする可能性があることです。接続プールへの分離レベルは、Webサイトに大混乱をもたらす可能性があります。ランダム文の意味は、コミットされていない読み取りで実行される場合があります。
廃棄されたMSは接続上のものをクリーンアップする機会があるため、Javedアプローチの方がはるかに優れています。
編集 Javedのアプローチでパフォーマンスの問題が発生している場合は、独自のトランザクションマネージャーのローリングを検討できます。
おそらくやりたいこと:
- 現在のトランザクションのスタックを保持する
- トランザクションがコミットされたときに、作成者スレッドにいることを確認します
- 破棄時にトランザクション分離を以前の状態にリセットする
- トランザクションがコミットされなかった場合の破棄のロールバック。
- ネストされたロールバックをサポートします。
他のヒント
私は、MicrosoftのSQL Serverグループのツールチームの開発者です。多くのアプリケーションはトランザクションの一貫性にあまり敏感ではありません。特に、レポートを作成するアプリや、時折矛盾するデータが世の終わりにならないようなアプリを書く場合はそうです。もちろん、金融アプリケーションなど、データの不一致に対する耐性が非常に低いものを作成する場合は、おそらく他のソリューションを検討する必要があります。
コミットされていない読み取りの使用を選択した場合、 C#の拡張メソッドを使用して便利なソリューションをブログに掲載しました。
{評判が悪いためコメントを投稿できないため、これを回答として入力します}
System.TransactionsでIsolationLevelを使用し、トランザクションブロック内に新しいLinqコンテキストを作成すると、SQL ServerはDTCを呼び出してトランザクションを調整しようとします。それはちょうど私に起こり、全く予想外でした。
.NetでのトランザクションおよびDTCの(なんとなく驚くべき)副作用については、このドキュメント。NET Framework 2.0でのSystem.Transactionsの紹介は、Juval Lowyが非常によく説明しており、まだ完全に有効です(.Net4)。読む価値があります。 (コメントを投稿することもできます...可能であれば。)