简体   繁体   English

Web 应用程序的最佳 SQL Server 隔离级别?

[英]Best SQL Server isolation level for web application?

We have a website using ASP.NET MVC and SQL Server 2008 and we are using the default transactionscope isolation level which is Serializable.我们有一个使用ASP.NET MVCSQL Server 2008 的网站,并且我们使用的是可序列化的默认事务范围隔离级别。 But it makes the application unusable if any transaction is opened as we have a table that being used by almost everything and it runs like但是如果任何事务被打开,它就会使应用程序无法使用,因为我们有一个几乎所有东西都在使用的表,它运行起来就像

select * from table1 where id = 1

So I think it locks the whole table when the above is executed.所以我认为在执行上述操作时它会锁定整个表。

I have been reading what could be the best option for web application with lot of transactions.我一直在阅读具有大量事务的 Web 应用程序的最佳选择。

I am kind of sold on Snapshot isolation level.我有点喜欢 Snapshot 隔离级别。 Which give the best of everything:这提供了最好的一切:

  • Data protection when read data is changed by throwing error.通过抛出错误更改读取数据时的数据保护。
  • Also allows read of data that's in transaction.还允许读取事务中的数据。

Which isolation level could be for web application as per your experience?根据您的经验,哪种隔离级别可以用于 Web 应用程序?

Edit: Default isolation level is from transactionscope, just to clarify why I mentioned serializable as default.编辑:默认隔离级别来自事务范围,只是为了澄清我为什么提到可序列化为默认值。

I read lots of blogs and answers here suggesting using no_lock for select, but that is kind of a hack if you ask me.我在这里阅读了很多博客和答案,建议使用 no_lock 进行选择,但如果你问我,那是一种黑客。 In a real life scenario maybe 99.99% of the time it will be OK.在现实生活中,可能 99.99% 的时间都可以。 And that is something fine for Facebook, Twitter or Stack Overflow.这对 Facebook、Twitter 或 Stack Overflow 来说很好。 Who cares if data is corrupted.谁在乎数据是否损坏。 But my take on it is if we use transaction isolation then it must be 100% guaranteed architecture.但我的看法是,如果我们使用事务隔离,那么它必须是 100% 保证的架构。 Otherwise don't use it at all and add some other data integrity checks with a trigger or something.否则根本不要使用它并使用触发器或其他东西添加一些其他数据完整性检查。

I suppose this question may be a better fit for serverfault.com, that said here's my understanding of the topic:我想这个问题可能更适合 serverfault.com,这是我对这个话题的理解:

First, since when the default isolation level became Serializable, I thought it was Read Committed!首先,因为当默认隔离级别变为 Serializable 时,我认为它是 Read Committed!

Second, Snapshot may not be a good idea as that effectively uses the tempdb(which for the most part sits in the memory) to store concurrent versions of the data, so with any luck you will run out of RAM on 1-2-3.其次,快照可能不是一个好主意,因为它有效地使用了 tempdb(它大部分位于内存中)来存储数据的并发版本,所以运气好的话你会在 1-2-3 上用完 RAM .

Third, serialization level is not an all-or-nothing endeavor, instead you should look at each and every query and set it per query, using query hints or whatever.第三,序列化级别不是一个全有或全无的努力,相反,您应该查看每个查询并使用查询提示或其他方式为每个查询设置它。 I would say for your magic select statement that is used everywhere you may even want to go with (nolock) hint (assuming the underlying table is 99.99% readonly; BTW if you notice yourself doing too much readonly stuff that's an indication that you should look into caching, whether native ASP.NET cache or Memcached or whatever) while the rest may use read committed.我会说你的魔法选择语句在任何地方使用,你甚至可能想要使用 (nolock) 提示(假设基础表是 99.99% 只读的;顺便说一句,如果你注意到自己做了太多只读的东西,这表明你应该看看进入缓存,无论是本机 ASP.NET 缓存还是 Memcached 或其他),而其余部分可能使用已提交的读。 Only on rare occasions (eg an automaintained lookup table) you want anything higher than that.只有在极少数情况下(例如自动维护的查找表),您才想要比这更高的值。

Forth, don't overuse pessimistic locking altogether.第四,不要完全过度使用悲观锁。 Much smarter choice is to go optimistic locking instead, eg insert hoping there's no dupe and deal with a failing constraint afterward and things like that.更明智的选择是改为使用乐观锁定,例如插入希望没有欺骗,然后处理失败的约束等等。 For updates, you can add timestamp column and include that in your where clause.对于更新,您可以添加时间戳列并将其包含在您的 where 子句中。 If somebody else hijacked the update before you, the rowcount will be 0. Etc.如果其他人在您之前劫持了更新,则行数将为 0。等等。

Hope this makes sense.希望这是有道理的。

You should use read committed snapshot in the database.您应该在数据库中使用读提交的快照。 This isolation level gives the highest degree of concurrency, at the cost of maintaining a version store during updates.此隔离级别提供了最高程度的并发性,但代价是在更新期间维护版本存储。 If your app is read intensive and not oltp intensive then this trade-off is worth.如果您的应用是读取密集型的而不是 oltp 密集型的,那么这种权衡是值得的。

If you enable read committed snapshot in your database, then transactions under read committed isolation will automatically use the snapshot isolation.如果您在数据库中启用读提交快照,那么在读提交隔离下的事务将自动使用快照隔离。

The serializable isolation level is way overkill usually, a true performance hog.可序列化的隔离级别通常是一种矫枉过正的方式,一个真正的性能猪。 Read committed (simple, no snapshot) is good but it can cause problems as it blocks reads vs. writes.已提交读(简单,无快照)很好,但它会导致问题,因为它会阻止读取与写入。

One of the best strategies is Row Versioning .最好的策略之一是行版本控制 You can set this at the database level like:您可以在数据库级别进行设置,例如:

ALTER DATABASE YourDatabaseName SET READ_COMMITTED_SNAPSHOT ON;

This basically does nonblocking reads by default.默认情况下,这基本上是非阻塞读取。 See also Row Versioning-based Isolation Levels in the Database Engine .另请参阅数据库引擎中基于行版本控制的隔离级别

A good RDBMS would only be locking the row indicated by "id=1", not the whole table, when you issue such a SELECT.当您发出这样的 SELECT 时,一个好的 RDBMS 只会锁定由“id=1”指示的行,而不是整个表。 Serializable isolation level is just fine provided that the database provides reasonable row locking, and that all pending locks are released at the end of each web request;如果数据库提供合理的行锁定,并且在每个 Web 请求结束时释放所有挂起的锁,则可序列化隔离级别就可以了; this generally means closing the database connection at the end of a request, or alternatively issuing a ROLLBACK or COMMIT if the connection is to be re-used again for a subsequent request.这通常意味着在请求结束时关闭数据库连接,或者如果连接要再次用于后续请求,则发出 ROLLBACK 或 COMMIT。

You need to go with read committed and do some optimistic locking in your app.您需要使用已read committed并在您的应用程序中进行一些乐观锁定 This seems to be more robust in most cases.在大多数情况下,这似乎更健壮。

Also have a look how stackoverflow team handled their locking issues.还可以看看stackoverflow 团队如何处理他们的锁定问题。

I think The best Isolation Level is Snapshot Isolation Level because It Will read the last Saved Data in the Table If the other transaction will not completes and no lock and no Dirty read So I best To use Snapshot Isolation Level better than Read Committed我认为最好的隔离级别是快照隔离级别,因为它会读取表中最后保存的数据如果另一个事务没有完成并且没有锁也没有脏读所以我最好使用快照隔离级别比读提交更好

How you can Do this by two Ways如何通过两种方式做到这一点

1-alter database testing set allow_SnapShot_Isolation on ; 1-更改数据库测试集allow_SnapShot_Isolation on ; or 2-alter database testing set Read_Committed_Snapshot on ;或 2-alter 数据库测试集 Read_Committed_Snapshot on ;

I hope To Be Useful For The Reader Mahmoud Shahin Egypt 0201288846966我希望对读者有用 Mahmoud Shahin 埃及 0201288846966

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SQL Server表隔离级别和锁定问题 - SQL Server table isolation level and lock issue 在SQL Server的.NET / Entity Framework中设置事务隔离级别 - Setting Transaction Isolation Level in .NET / Entity Framework for SQL Server linq to sql,DataContext中的隔离级别 - isolation level in linq to sql , DataContext 从Web应用程序向SQL Server表插入多行 - 最佳实践 - Inserting multiple rows into SQL Server table from web application - best practice 在.Net 中,我可以指定默认的应用程序范围的隔离级别吗? - In .Net, can I specify a default application wide Isolation Level? 相对AJAX路径与Web服务器上的应用程序级别无关 - Relative AJAX path independent of application level on web server 如何通过 SQL 查询(即在应用程序级别而不是 SQL 服务器级别)之外应用订单? - How to apply the order by outside of the SQL query (that is - at application level instead of the SQL server level)? 从.NET应用程序执行SQL Server脚本的最佳实践? - Best practices for executing SQL Server Scripts from a .NET Application? Windows窗体应用程序从sql服务器迁移到oracle的最佳方法 - best way to migrate a windows forms application from sql server to oracle SQL Server CE应用程序中的独特记录插入最佳实践 - Unique Record Insertion Best Practice in SQL Server CE Application
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM