连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: 原文:连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法  本文出处:http://www.cnblogs.com/wy123/p/6110349.html    之前遇到过这么一种情况:   连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持续较长时间,有时间持续时间较短,没有什么规律。
原文: 连接SQLServer时,因启用连接池导致孤立事务的原因分析和解决办法

 

本文出处:http://www.cnblogs.com/wy123/p/6110349.html 

 

之前遇到过这么一种情况:

  连接数据库的部分Session会出现不定时的阻塞,这种阻塞时长时短,有时候持续较长时间,有时间持续时间较短,没有什么规律。
   之后分析相关存储过程和代码写法,发现是阻塞源头的存储过程中开启了事务,而应用程序在调用存储过程发生异常之后没有进行特别的处理(提交或者回滚),
   那么在执行方法发生异常之后,连接关闭了,但是数据库中遗留有活动事务(dbcc opentran对应的SessionId是sleeping状态),于是就产生了阻塞。
   关键是活动事务会不定时自己消失,就有点诡异了,这是本文的重点。

 

这种机制跟连接池有关:

当应用程序连接数据库的时候开启了连接池,如果应用程序调用了一个开启了事务操作的存储过程,
当发生异常的时候,有可能会出现数据库连接关闭,而存储过程中的事务既没有提交,也没有回滚的情况。
这种情况下就会产生“孤立事务”,也就是说,因为打开事务的数据量连接断掉了,而事务还处于活动状态,
实际上开启连接池的情况下,数据库连接的关闭,并不是物理上的关闭,而是将数据库连接返回到连接池。
此时如果没有外界的干预,包括没有对这个数据库连接没有被重用,或者这个连接没有物理断开,或者是没有重启应用程序,或者没有数据库服务器,这个事务将一直持续下去。
因为活动事务将阻塞其他Session对相关表的排他性访问,所以就表现为阻塞。

 

 

 

如何判断是否发生了连接池中的连接重用

首先,一个连接数据库的过程中,有没有重用连接池中的连接,在SQL Server中有哪些区别?
以ado.net为例,如果在连接字符串中加入pooling=false;则表示不启用连接池.
如下,连续执行两次数据库访问,两次数据库访问均在连接字符串中加入了pooling=false;表示不启用连接池

  

  如下是观察到profile中的连接动作,注意这里第一次连接断开之后,有一个logout,第二次访问数据的时候,有一个login

  

  如果将上述两个方法中连接字符串中的pooling=false;改为pooling=true;再次连续执行两个方法,
  会发现第二次连接数据的之前,也即在第一个logout之后,第二次login之前,有一个exec sp_reset_connection的动作。
  exec sp_reset_connection的执行标志着连接从连接池中重用了连接,关于这个动作的作用下面再说

 

 

什么情况下会出现数据库连接关闭,而事务保持活动状态 

  首先,参考如下截图,编写一个事务性存储过程,用waitfor delay '00:00:50'的方式延长其事务提交时间,造成连接超时(默认ado.net连接30秒)

 

 

在ado.net中调用这个存储过程,连接超过30秒之后超时异常,当前执行方法的数据库连接被关闭,此时并不关闭Visual Studio,模拟应用程序并没有终止

 

   

  此时查询数据中的活动事务,发现有一个活动事务,活动事务是上次执行“TimeoutFunction”造成的,
  但此时“TimeoutFunction”发生了异常,数据库连接被正常关闭,  
  此时,执行这个方法造成的事务还是活动状态的,如下截图

 

而此时观察SessionId = 57的状态,他是sleeping啊,已经开始呼呼睡大觉了。 

 

如果此时对事务中的表执行查询操作,会发现是被阻塞的,事实上t1这张表在上述方法执行之前一行数据都没有

 

 

数据库连接被重用,第一次连接遗留在数据库中的事务被回滚

  上面在执行第一个方法之后,并没有中断VS的调试状态,我们继续执行第二个方法,此时第二个方法会重用第一个方法的数据库连接,
  至于为什么说他就重用了第一个方法的数据库连接,一开始就说了。
  当执行exec sp_reset_connection的时候,活动事务被回滚。查询能够正常执行。如下截图

 

  查询在exec sp_reset_connection之后正常完,因为事务是被回滚的,所以t1表没有任何数据

 

  上述示例就模拟出来类似这么一种场景,当连接字符串中开启了连接池之后
  一个方法执行超时连接被关闭之后,其调用的存储过程中的事务并没有显式的提交或者回滚,造成连接关闭而事务继续保持活动状态的情况
  比如web程序,一个方法执行完成之后,连接超时但是正常关闭(归还连接池),事务保持活动状态,
  此时web服务器并没有停止下来,也就是应用程序没有直接关闭,也就是类似于Visual Studio继续保持DEBUG状态,
  此时事务一直保持活动状态知道连接被重用(或者应用程序被关闭),那么其他Session发起对活动事务锁定的对象,就会发生阻塞。
  问题就出在这里,主观上无法保证连接池中的那个连接什么时候被重用,也就无法保证活动事务要持续多久,
  如果活动事务一直保持,那么阻塞就一直保持,这显然是不可接受的

 

关于sp_reset_connection的作用,我就懒得打字了,参考《Microsoft SQL Server企业级平台实践》第316页

 

如何避免连接关闭而事务保持活动

  1,本质因为存储过程执行时间超过了连接的时间导致连接关闭的,那么就可以从分析事务性操作超时的原因入手。

  2,可以在应用程序的代码中catch的中,进行异常处理时候,保证连接关闭之前,活动事物最终提交或者回滚(作出明确的处理)

  3,关闭连接池,这种情况下,任何被物理关闭的数据库连接,其发起的未提交事务都将被回滚,但连接池也是为了提高数据库性能,可行性不大。

  4,从性能上以及连接池机制中分析,以上只能缓解这个问题,而逃不过这个问题,
    实际上,面对连接超时断开而是事务继续保持活动状态这种情况,在存储过程的事务性操作中加入try catch也是无济于事的,
    那么就可以使用SET XACT_ABORT ON;命令,确保在任何异常情况下,对事务进行回滚。关于XACT_ABORT可参考联机丛书。

    

 

总结:本文浅析了启用数据库连接池的条件下,在对数据库访问异常的情况下,造成孤立事物现象进行了原因进行了分析以及可行的解决方法尝试。

   从中得到一个教训,就是在对数据访问异常处理的时候,应用程序中一定要确保连接与事物的同步释放。同时,对事务处理的时候,存储过程中一定要做到严谨的事务控制和异常处理机制。

   确保在异常情况下,事务能够直接回滚,避免引起类似的阻塞。

 

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
3月前
|
SQL 数据库 数据安全/隐私保护
SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
【8月更文挑战第14天】解决SQL Server事务复制Log Reader作业因数据库所有者问题无法启动的方法:首先验证数据库所有者是否有效并具足够权限;若非,使用`ALTER AUTHORIZATION`更改为有效登录名。其次,确认Log Reader使用的登录名拥有读取事务日志所需的角色权限。还需检查复制配置是否准确无误,并验证Log Reader代理的连接信息及参数。重启SQL Server Agent服务或手动启动Log Reader作业亦可能解决问题。最后,审查SQL Server错误日志及Windows事件查看器以获取更多线索。
|
2月前
|
SQL 网络协议 数据库连接
已解决:连接SqlServer出现 provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程【C#连接SqlServer踩坑记录】
本文介绍了解决连接SqlServer时出现“provider: Shared Memory Provider, error: 0 - 管道的另一端上无任何进程”错误的步骤,包括更改服务器验证模式、修改sa用户设置、启用TCP/IP协议,以及检查数据库连接语句中的实例名是否正确。此外,还解释了实例名mssqlserver和sqlserver之间的区别,包括它们在默认设置、功能和用途上的差异。
|
2月前
|
SQL 存储 监控
SQLServer事务复制延迟优化之并行(多线程)复制
【9月更文挑战第12天】在SQL Server中,事务复制延迟会影响数据同步性。并行复制可通过多线程处理优化这一问题,提高复制效率。主要优化方法包括:配置分发代理参数、优化网络带宽、调整系统资源、优化数据库设计及定期监控维护。合理实施这些措施可提升数据同步的及时性和可靠性。
|
3月前
|
SQL Java 数据库连接
JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
这篇文章提供了使用JDBC连接SQL Server 2008数据库进行增加、删除、查询和修改操作的基本步骤和示例代码。
|
3月前
|
SQL 监控 数据库
SQL Server如何判断哪些会话/连接是长连接?
【8月更文挑战第14天】在SQL Server中,判断长连接可通过活动监视器查看持续时间和状态;查询`sys.dm_exec_sessions`获取持续时间超阈值的会话;利用性能监视器跟踪“User Connections”计数器变化;审查应用代码中连接池配置;或分析网络流量寻找持久连接。这些方法有助于管理和优化连接。
|
2月前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
113 0
|
3月前
|
SQL 监控 供应链
|
4月前
|
SQL 存储 关系型数据库
|
3月前
|
SQL 数据库连接 网络安全
SQLServer非默认端口下事务复制代理作业服务无法启动的处理
【8月更文挑战第14天】若SQL Server非默认端口下的事务复制代理作业无法启动,可按以下步骤解决:1) 确认服务器连接字符串正确无误,包括非默认端口号;2) 检查防火墙设置,确保允许非默认端口的连接;3) 核实SQL Server配置已启用非默认端口;4) 查阅代理作业日志寻找错误详情;5) 重启SQL Server与Agent服务;6) 使用工具测试非默认端口的连接性。如问题持续,请寻求专业支持。
|
3月前
|
SQL 安全 Java
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接。错误:“The server selected protocol version TLS10 is not accepted by client
463 0