【问题标题】:LINQ + TransactionScope will not change isolation level in SQL Server ProfilerLINQ + TransactionScope 不会更改 SQL Server Profiler 中的隔离级别
【发布时间】:2011-04-24 02:26:01
【问题描述】:

我使用以下格式使用 linq 提交对我的数据库的更改。

Begin Transaction (Scope Serialized, Required)
    Check Business Rule 1...N
    MyDataContext.SubmitChanges()
    Save Changes Done In Previous Query To Log File
End Transaction Scope

但在 SQL Server 分析器中,我在 Connection:Start 中看到以下行。

set transaction isolation level read committed

我经历了这个 (http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/93a45026-0425-4d49-a4ac-1b882e90e6d5) 并认为我有答案;

直到我在 Microsoft Connect 上看到 (https://connect.microsoft.com/VisualStudio/feedback/details/565441/transactionscope-linq-to-sql?wa=wsignin1.0)。

谁能告诉我我的代码实际上是在序列化隔离级别下执行的,还是实际上只是在读取提交下运行?

【问题讨论】:

  • 我倾向于相信您在 Profiler 中看到的内容...
  • 但是其中一篇文章也说profiler只显示连接开始时的隔离级别,:S
  • 我应该查找哪些语句?我发现了一些非常有趣的东西,Audit:Login statemnts immidiatly after the above query has set transaction isolation level serializable,但是到那时我想在序列化隔离中执行的查询已经被执行了。
  • @Mitch,稍微微妙一点,我也无法分辨TM: Begin Tran 中 tran 的隔离级别,但我可能缺少一列
  • @Mitch,虽然我经常使用 Profiler 来查看数据库级别真正发生了什么,在这种情况下,来自 Profiler 的 Audit Login 语句将显示隔离级别在设置之前。很难在 Profiler 中查看隔离级别的设置(如 divega 的 cmets 中所述,entityframework.codeplex.com/workitem/1712)。要确定地知道,请查看 sys.dm_exec_session 视图中的会话记录。 Sam 提到了一种方法来做到这一点。你会发现 Profiler 上报的Audit Login 经常与当前隔离级别不匹配。

标签: linq-to-sql sql-server-2008 transactions sql-server-profiler isolation-level


【解决方案1】:

这取决于您如何创建交易。

如果您执行内联 SQL 来启动它(例如,BEGIN TRAN),L2S 将不知道该事务,并将在 READ COMMITTED 中启动一个新的嵌套事务。

但是,如果您使用 System.Transaction,或者在您的 DataContext 上设置了事务,SubmitChanges 将参与该事务。

如果您选择 TM: Begin TranTM: Commit Tran 事件类,您可以在 Profiler 中看到这些事务的开始和停止。

注意:ADO.Net 不会下发BEGIN TRAN,也不会批量下发SET TRANSACTION ISOLATION,这是在较低级别完成的。

如果您真的想要确认该行为,请在表上创建一个触发器,将当前隔离级别插入到日志表中并检查它。

你可以通过运行来获取你当前的隔离级别:

SELECT CASE transaction_isolation_level 
WHEN 0 THEN 'Unspecified' 
WHEN 1 THEN 'Read Uncommitted' 
WHEN 2 THEN 'Read Committed' 
WHEN 3 THEN 'Repeatable Read' 
WHEN 4 THEN 'Serializable' 
WHEN 5 THEN 'Snapshot' END AS TRANSACTION_ISOLATION_LEVEL 
FROM sys.dm_exec_sessions 
where session_id = @@SPID

【讨论】:

  • 我开始我的事务,如我的帖子中所示的 Begin Transaction (Scope Serialized, Required),为什么它没有在服务器分析器中显示隔离级别?请参阅我发布的链接。
【解决方案2】:

我的猜测是你创建了 DataContext,然后使用了 TransactionScope。您必须在 TransactionScope 内打开连接,以便它加入。

【讨论】:

  • 没有。那里有一个属性来指示上下文使用任何现有事务(或需要新事务)。这是一个完全不同的问题。
【解决方案3】:

来自http://entityframework.codeplex.com/workitem/1712

TransactionScope 使用远程 API 调用而不是 SQL 命令在 SQL Server 中执行事务。这些 API 调用不包含在 SQL Profiler 的标准跟踪中。

您可以通过转到“事件选择”页面,单击“显示所有事件”复选框并从“交易”类别中选择所有事件来包含它们。这将允许您查看诸如“TM: Begin Tran Starting”、“SQLTransaction”和“TM: Begin Tran Completed”之类的事件实际发生的时间。

您还可以在“事件选择”页面中检查 TSQL 事件的 TransactionID 列,以查看每个正在执行的 SQL 批处理与哪个事务相关联。

不幸的是,我不知道有一种直接的方法来观察在 SQL Profiler 中执行每个命令的有效隔离级别。但是有一个间接的方式...

打开连接后,您将在跟踪中看到“审核登录”事件。在许多情况下,此事件将包含隔离级别。现在,“审核登录”发生在设置实际隔离级别之前,因此报告的隔离级别不会准确反映即将开始的事务的隔离级别。以下是有关如何解释它的一些提示: 当一个连接打开实际命中一个新连接时,它总是会报告默认的事务隔离级别,例如您将看到“设置事务隔离级别读取未提交”(正如我所说,这与您的事务的有效隔离级别无关,因为该级别将在稍后设置) 在打开一个连接然后返回到连接池(即关闭)后,后续打开的连接实际上将重用池中的现有连接。在这种情况下,“审核登录”将报告连接上次返回池时设置的隔离级别。这可以帮助您在事后查看所使用的隔离级别。 例如。在您的代码 sn-p 中,连接最后一次打开以回滚事务(因为您没有将事务显式标记为已完成)。在该“审核登录”事件中,您应该能够看到之前使用连接执行查询时有效的隔离级别,由“设置事务隔离级别读取未提交”行表示。

【讨论】:

    猜你喜欢
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-04
    • 2010-12-12
    相关资源
    最近更新 更多