LINQ + TransactionScope 不会更改 SQL Server Profiler 中的隔离级别
我使用以下格式通过 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)。
有人可以告诉我我的代码是否实际上是在序列化隔离级别下执行的,还是实际上只是在已提交的读下运行?
I'm using the following format for commiting changes to my db using 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
But in the SQL Server profiler I see the following line in the Connection:Start.
set transaction isolation level read committed
I went through this (http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/93a45026-0425-4d49-a4ac-1b882e90e6d5) and thought I had an answer;
Until I saw this (https://connect.microsoft.com/VisualStudio/feedback/details/565441/transactionscope-linq-to-sql?wa=wsignin1.0) on Microsoft Connect.
Can someone please tell me whether my code is actually executed under Serialized Isolation Level or whether it is infact just running under read committed?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这取决于您如何创建交易。
如果您执行内联 SQL 来开始它(例如
BEGIN TRAN
),L2S 将不会意识到该事务,并且会在READ COMMITTED
中启动一个新的嵌套事务。但是,如果您使用 System.Transaction,或者在
DataContext
上设置了事务,则 SubmitChanges 将参与该事务。如果您选择
TM: Begin Tran
和TM: Commit Tran
事件类,您可以在 Profiler 中看到这些事务的启动和停止。注意:ADO.Net 不会批量发出
BEGIN TRAN
也不会发出SET TRANSACTION ISOLATION
,这是在较低级别完成的。如果您确实想要确认该行为,请在表上创建一个触发器,将当前隔离级别插入到日志记录表中并对其进行检查。
您可以通过运行以下命令来获取当前的隔离级别:
It depends on how you created the transaction.
If you executed inline SQL to begin it (EG.
BEGIN TRAN
), L2S will not be aware of the transaction and will spin up a new nested one inREAD COMMITTED
.However, if you used System.Transaction, or have a transaction set on your
DataContext
, SubmitChanges will participate in that transaction.You can see these transaction starting and stopping in Profiler if you choose the
TM: Begin Tran
andTM: Commit Tran
event classes.Note: ADO.Net does not issue
BEGIN TRAN
nor does it issueSET TRANSACTION ISOLATION
in batches, this is done at a lower level.If you really want to confirm the behavior, create a trigger on a table that inserts the current isolation level into a logging table and check on it.
You can pick up your current isolation level by running:
我的猜测是您创建了 DataContext,然后使用了 TransactionScope。您必须在 TransactionScope 内打开连接才能登记。
My guess is you created the DataContext, then used the TransactionScope. You have to open the connection inside the TransactionScope in order for it to enlist.
来自 http://entityframework.codeplex.com/workitem/1712
TransactionScope 使用远程 API 调用而不是用于在 SQL Server 中执行事务的 SQL 命令。这些 API 调用不包含在 SQL Profiler 的标准跟踪中。
您可以通过转到“事件选择”页面,单击“显示所有事件”复选框并从“交易”类别中选择所有事件来包含它们。这将允许您查看诸如“TM:Begin Tran 开始”、“SQLTransaction”和“TM:Begin Tran 完成”等事件实际发生的时间。
您还可以在“事件选择”页面中检查 TSQL 事件的 TransactionID 列,以查看正在执行的每个 SQL 批处理与哪个事务关联。
不幸的是,我不知道有什么直接方法可以观察 SQL Profiler 中执行的每个命令的有效隔离级别。但是有一种间接的方法......
当打开连接时,您将在跟踪中看到“审核登录”事件。在许多情况下,此事件将包含隔离级别。现在,“审核登录”发生在设置实际隔离级别之前,因此报告的隔离级别将无法准确反映即将启动的事务的隔离级别。以下是有关如何解释它的一些提示:
当一个连接打开实际上到达一个新连接时,它总是会报告默认的事务隔离级别,例如,您将看到“设置事务隔离级别读取未提交”(正如我所说,这与事务的有效隔离级别无关,因为该级别)将在稍后设置)
在连接打开并返回到连接池(即关闭)后,后续打开的连接实际上会重用池中现有的连接。在这种情况下,“审核登录”将报告上次连接返回池时设置的隔离级别。这可以帮助您在事后查看所使用的隔离级别。
例如,在您的代码片段中,连接最后一次打开以回滚事务(因为您尚未将事务显式标记为已完成)。在该“审核登录”事件中,您应该能够看到先前使用连接执行查询时有效的隔离级别,由“设置事务隔离级别读取未提交”行表示。
From http://entityframework.codeplex.com/workitem/1712
TransactionScope uses remote API calls rather than SQL commands to perform transactions in SQL Server. Those API calls are not included in the a standard trace in SQL Profiler.
You can include them by going to the "Event Selection" page, clicking on the "Show all events" checkbox and the selecting all the events from the Transactions category. This will allow you to see when such events as 'TM: Begin Tran Starting', 'SQLTransaction' and 'TM: Begin Tran Completed' actually occur.
You can also check the TransactionID column for the TSQL events in the "Event Selection" page to see the to which transaction each SQL batch being executed is associated.
Unfortunately I don't know of a direct way to observe the effective isolation level under which each command is being executed in SQL Profiler. But there is an indirect way...
When a connection is opened you will see an 'Audit Login' event in the trace. In many cases this event will contain the isolation level. Now, the 'Audit Login' happens before the actual isolation level is set, so the reported isolation level won't accurately reflect the isolation level of the transaction that is about to start. Here are some tips on how to interpret it:
When a connection opening actually hits a new connection it will always report the default transaction isolation level, e.g. you will see 'set transaction isolation level read uncommitted' (as I said, this is unrelated to the effective isolation level of your transaction as that one will be set at a later point)
After a connection has been opened and then returned to the connection pool (i.e. closed), subsequent connection openings will actually reuse that existing connection from the pool. In this case the 'Audit Login' will report the isolation level that was set when the connection got returned to the pool the last time. This can help you see the isolation level that was used, after the fact.
E.g. in your code snippet, the connection is open for a last time to roll back the transaction (because you have not marked the transaction as completed explicitly). In that 'Audit Login' event you should be able to see the isolation level that was effective when the connection was previously used to execute the query, represented by the line 'set transaction isolation level read uncommitted'.