在事务中运行 sp_reset_connection 时的行为是什么?我正在寻求澄清,以便我可以决定是否需要重新构建我的代码,或者我是否可以保留原样。
我有一个使用ORM(Petapoco)的c#应用程序,它似乎不尊重环境事务(System.Transactions.TransactionScope)。我可以在Sql Profiler中看到事务,但在事务中的每次调用之前,ORM都在发送 sp_reset_connection 调用。我的环境事务处理完成后,我也在Sql Profiler中看到了Transaction Commit事件。
我在StackOverflow上看到其他问题,建议在调用 sp_reset_connection 时重置事务隔离范围(请参阅:What does “exec sp_reset_connection” mean in Sql Server Profiler?),但我找不到任何有关发生情况的信息特别是在事务内部调用 sp_reset_connection 时。
答案 0 :(得分:3)
sp_reset_connection
存储过程没有很好地记录,因为它是一个内部存储过程,从不直接调用。请注意,以后可能会更改或删除,恕不另行通知。话虽如此,了解一些有关故障排除和关联活动跟踪数据的内部结构非常有用。
proc的目的是将连接环境状态恢复为新打开的连接的状态以支持连接池。客户端API通过在从池中重新使用的连接发出请求时设置TDS protocol status field的RESETCONNECTION
或RESETCONNECTIONSKIPTRAN
位来指定是否要重置连接。当设置了其中任何一个标志时,SQL Server在内部调用您在跟踪中看到的sp_reset_connection
RPC。
TDS协议文档描述了这些标志,因此我们可以推断这是sp_reset_connection
所涵盖的内容。以下是文档的摘录:
RESETCONNECTION(在TDS 7.1中引入)(从客户端到服务器)重置 处理事件之前的这个连接。仅为事件类型设置 批处理,RPC或事务管理器请求。如果客户想要设置 这一点,它必须是消息的第一个数据包的一部分。这个 通知服务器清理连接的环境状态 回到默认环境设置,有效地模拟了一个 注销和后续登录,并提供服务器支持 连接池。如果在a中设置,则该位应该被忽略 数据包不是消息的第一个数据包。
此状态位不得与...一起设置 RESETCONNECTIONSKIPTRAN位。分布式事务和隔离 级别不会被重置。 0x10的
RESETCONNECTIONSKIPTRAN(在TDS 7.3中引入)(从客户端到 server)在处理事件之前重置连接但不修改 交易状态(状态在前后保持不变 重置)。会话中的事务可以是本地事务 从会话开始,或者它可以是分布式的 会话入伍的交易。这个状态位不能 与RESETCONNECTION位一起设置。除此以外 与RESETCONNECTION相同。
低级客户端API(此处为SqlClient)通过根据需要设置这些标志来间接控制sp_reset_connection
的行为。当在TransactionScope
之外重用连接时,RESETCONNECTION
标志被设置为可以在此网络数据包跟踪(Wireshark)中看到:
以下是使用块TransactionScope
范围内对重用连接发出的第一个请求的跟踪:
如您所见,TransactionScope
内的重置不会回滚事务。因此,即使您的ORM遵循打开/执行/关闭模式进行数据访问,您的外部TransactionScope
事务上下文也将受到尊重。只要在退出事务范围之前调用TransactionScope.Complete
,就会提交转换。您可以在Profiler跟踪中包含TM Commit Tran completed事件,以便在TransactionScope
退出时查看提交。
BTW,不推荐使用Profiler / SQL跟踪。使用扩展事件而不是前进。另外,如其他答案所示,请确保在使用TransactionScope时指定所需的事务隔离级别(例如,读取已提交)。默认是可序列化的,可能会产生不必要的阻塞和死锁等副作用。我建议你只有在特别需要严格的隔离级别时才使用serializable。