2011-12-13 81 views
3

我一直在寻找一段时间,现在在这里和其他地方,找不到一个很好的答案,为什么Linq-TO-SQL与NOLOCK是不可能的。LINQ-TO-SQL NOLOCK(不ReadUncommitted)

每次我搜索如何将(NOLOCK)提示应用于Linq-To-SQL上下文(应用于1个sql语句)时,人们经常会回答强制将IsolationLevel设置为ReadUncommitted的事务(TransactionScope)。那么 - 他们很少告诉这导致连接打开一个事务(我也读过的地方必须确保手动关闭)。

在我的应用程序中原样使用ReadUncommitted实际上并不好。现在我已经使用上下文语句为对方内的相同的连接。像:

using(var ctx1 = new Context()) { 
    ... some code here ... 
    using(var ctx2 = new Context()) { 
     ... some code here ... 
     using(var ctx3 = new Context()) { 
      ... some code here ... 
     } 
     ... some code here ... 
    } 
    ... some code here ... 
} 

随着1秒,很多用户在同一时间,更改隔离级别的总执行时间,将导致上下文等待对方释放,因为在连接池中的所有连接的连接正在使用。

因此,改变为“nolock”的原因之一是避免死锁(现在我们每天有1个客户死锁)。上述的后果只是另一种僵局,并不能解决我的问题。

所以我知道我可以做的是:同一个连接

    1. 避免嵌套使用在服务器

    增加连接池的大小,但我的问题是:

    1. 这是不可能在不久的将来,因为许多代码行重新分解,它会与a (甚至没有开始评论这是好还是坏)
    2. 即使这当然会起作用,这就是我所说的“症状治疗” - 因为我不知道应用程序将会增长多少,以及如果这是对未来的可靠的解决方案(然后我可能最终得到了很多更多的用户受到影响一个更糟糕的情况)

    我的想法是:

    1. 那么它是否真的是真实的, NoLock不可能(对于没有开始事务的每个语句)?
    2. 如果1是真的 - 它真的是真的没有其他人得到了这个问题,并解决它在一个通用的LINQ sql修改?
    3. 如果2是真的 - 为什么这不是别人的问题?
      1. 有没有另外的解决办法,我没有看过可能?
      2. 是否使用相同的连接(嵌套)很多次这么糟糕的做法,没有人有这个问题?
  • +1

    是*要被nolocked所有*操作?或*一些*?对于* all *,您可以通过'SET'使用连接级别的隔离级别,但是**重要**;在“辉煌”的举动,隔离级别** IS NOT **不同的使用相同的底层池连接的,之间的复位,所以如果你走这条路线,你需要明确'SET'适当地打开连接 –

    +1

    之后也:值得一看:http://www.brentozar.com/archive/2011/11/theres-something-about-nolock-webcast-video/ –

    回答

    2

    1:LINQ到SQL确实不允许你表示类似NOLOCK提示;它可能写你自己的TSQL,但使用ExecuteQuery<T>

    2:以优雅的方式解决将是非常复杂的,坦率地说;而且你很可能会不恰当地使用它。例如,在“僵局”的情景,我敢打赌,实际上它是UPDLOCK,你应该使用(第一次读期间),以确保第一读取需要锁;这可以防止一秒钟后查询得到一个锁,所以你通常得到阻断,而不是僵局

    3:使用连接不一定是一个很大的问题(但请注意new Context()不会一般共享连接;共享连接,您将使用new Context(connection))。如果遇到这个问题,有三种可能的解决方案(如果我们排除“使用带有一丝支持的ORM”):使用一个明确的交易(不TransactionScope

    • - 它可以是一个连接级别的事务)来指定隔离级别
    • 编写自己的TSQL与提示
    • 使用连接级别的隔离级别(注意我添加注释的警告)

    IIRC还有一种方式分类e数据上下文和一些事务创建代码来控制它在内部创建的事务的隔离级别。

    +0

    谢谢您的非常好,快回答! –

    +0

    现在我已经用的TransactionScope和this.ExecuteCommand测试(“事务隔离级别设置读取未提交;”); (当然,我自己的clientcontext类来处理创建和IDisposable通用) 我们确实使用新的上下文(连接)来获得共享连接的好处.. 使用连接级别的隔离级别,这会影响共享的连接?听起来像这可能是我的解决方案? –

    +0

    @尼克 - 它是连接宽;该连接的任何用法都将使用最后一个隔离级别集合,它可能意味着来自SET的隔离级别,或者可能意味着事务的隔离级别。疯狂的事情。和:如前所述它**不**得到自动复位,所以如果你的猴子这一点,那么** **所有的'connection.Open()'必须发出一个'SET',以确保适当的**隔离*该级别用于该连接。但是 - 只要你明白**你在做什么(和**为什么**),它可以是有效的,是的。 –