没有手动提交事务,Mybatis 的 POOLED 连接池炸了

article/2025/10/6 20:25:00

错误原因: 事务不关,并且非事务交替进行
总的来说,就是先开启了事务连接,未提交或关闭,导致连接池连接全部占满。
此时进行一次非事务连接操作,但是因为此时已经没有可以空闲的连接,并且创建的连接数已经最大。
pooled 连接池会从活动的连接里面找一个 连接时间超过配置的 连接,

在这里插入图片描述
删除(设置失效标志,valid),
在这里插入图片描述
重新创建一个连接使用。但是这个旧对象(暂且称其为对象)在我们的事务集合里面仍然保留引用,此时已经不能用了(valid 为false),所以报错。

在这里插入图片描述
是高并发? 不可能, 挖一下!


使用的 POOLED 连接池<!-- 对事务的管理和连接池的配置 --><environments default="env_default"><environment id="env_default"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="${driver}" /><property name="url" value="${url}" /><property name="username" value="${username}" /><property name="password" value="${password}" /><property name="poolPingEnabled" value="true" /><property name="poolPingQuery" value="SELECT CURDATE()" /><!--<property name="poolMaximumCheckoutTime" value="1" />--><!--<property name="poolMaximumActiveConnections" value="1"/>--><!--<property name="poolMaximumIdleConnections" value="0"/>--><!--<property name="poolTimeToWait" value="1"/>--></dataSource></environment>

实现代码:

PooledDataSource.java/**
* This is a simple, synchronous, thread-safe database connection pool.
*
* @author Clinton Begin
*/
public class PooledDataSource implements DataSource {private static final Log log = LogFactory.getLog(PooledDataSource.class);private final PoolState state = new PoolState(this);private final UnpooledDataSource dataSource;// OPTIONAL CONFIGURATION FIELDSprotected int poolMaximumActiveConnections = 10; protected int poolMaximumIdleConnections = 5;protected int poolMaximumCheckoutTime = 20000; // 连接最长持有时间protected int poolTimeToWait = 20000;// 连接等待时间protected int poolMaximumLocalBadConnectionTolerance = 3;protected String poolPingQuery = "NO PING QUERY SET";protected boolean poolPingEnabled;protected int poolPingConnectionsNotUsedFor;private int expectedConnectionTypeCode;
……/*
* Invalidates the connection
* 这个字段判断 这个连接是否可用
*/
public void invalidate() {valid = false;
}private PooledConnection popConnection(String username, String password) throws SQLException {boolean countedWait = false;PooledConnection conn = null;long t = System.currentTimeMillis();int localBadConnectionCount = 0;while (conn == null) {synchronized (state) {if (!state.idleConnections.isEmpty()) {// Pool has available connectionconn = state.idleConnections.remove(0);if (log.isDebugEnabled()) {log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");}} else {// Pool does not have available connectionif (state.activeConnections.size() < poolMaximumActiveConnections) {// Can create new connectionconn = new PooledConnection(dataSource.getConnection(), this);if (log.isDebugEnabled()) {log.debug("Created connection " + conn.getRealHashCode() + ".");}} else {// Cannot create new connectionPooledConnection oldestActiveConnection = state.activeConnections.get(0); // **当不能创建新连接,并且没有空闲连接 可用的时候,从active中拿一个检查 连接时间是否超过poolMaximumCheckoutTime。**long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();if (longestCheckoutTime > poolMaximumCheckoutTime) {  // 超过了,就可以拿来用了。// Can claim overdue connectionstate.claimedOverdueConnectionCount++; state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;state.accumulatedCheckoutTime += longestCheckoutTime;state.activeConnections.remove(oldestActiveConnection);if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {try {oldestActiveConnection.getRealConnection().rollback();} catch (SQLException e) {/*Just log a message for debug and continue to execute the followingstatement like nothing happend.Wrap the bad connection with a new PooledConnection, this will helpto not intterupt current executing thread and give current thread achance to join the next competion for another valid/good databaseconnection. At the end of this loop, bad {@link @conn} will be set as null.*/log.debug("Bad connection. Could not roll back");}  }conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);// **new  一次,得到一个新连接。**conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());oldestActiveConnection.invalidate(); // 因为要维持连接数目,所以旧连接失效if (log.isDebugEnabled()) {log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");}} else {// Must waittry {if (!countedWait) {state.hadToWaitCount++;countedWait = true;}if (log.isDebugEnabled()) {log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");}long wt = System.currentTimeMillis();state.wait(poolTimeToWait);state.accumulatedWaitTime += System.currentTimeMillis() - wt;} catch (InterruptedException e) {break;}}}}if (conn != null) {// ping to server and check the connection is valid or notif (conn.isValid()) {if (!conn.getRealConnection().getAutoCommit()) {conn.getRealConnection().rollback();}conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));conn.setCheckoutTimestamp(System.currentTimeMillis());conn.setLastUsedTimestamp(System.currentTimeMillis());state.activeConnections.add(conn);state.requestCount++;state.accumulatedRequestTime += System.currentTimeMillis() - t;} else {if (log.isDebugEnabled()) {log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");}state.badConnectionCount++;localBadConnectionCount++;conn = null;if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {if (log.isDebugEnabled()) {log.debug("PooledDataSource: Could not get a good connection to the database.");}throw new SQLException("PooledDataSource: Could not get a good connection to the database.");}}}}}if (conn == null) {if (log.isDebugEnabled()) {log.debug("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");}throw new SQLException("PooledDataSource: Unknown severe error condition.  The connection pool returned a null connection.");}return conn;}
}  

http://chatgpt.dhexx.cn/article/J1ZW8EPG.shtml

相关文章

【Flink】报错 No pooled slot available and request to ResourceManager for new slot failed

文章目录 1.场景11.1 概述1.2 问题1.场景1 1.1 概述 改报错请参考:【Flink】Flink 1.9 升级 到 flink 1.12.4 报错 shaded netty4 AbstractChannel AnnotatedConnectException 错误描述 报错信息: java.util.concurrent.CompletionException:

Oracle 关于Pooled connection request timed out

发生场景&#xff1a; 系统异常卡死&#xff0c;报错&#xff1a; 通过查找日志和业务接口定位&#xff0c;是因为数据库连接池溢出导致链接不上&#xff0c;系统卡死 异常测试代码如下格式&#xff1a; 测试了一个1000次的链接&#xff0c;每次连接都持续30秒&#xff0c;链…

MyBatis POOLED连接池深入了解

往期内容&#xff0c;如下 一、MyBatis简介 二、MyBatis环境搭建 三、MyBatis入门案例 四、MyBatis自定义 五、MyBatis CRUD操作 六、Mybatis中参数和返回值的深入了解 七、MyBatis 配置文件标签 我们在实际开发中都会使用连接池&#xff0c;因为它可以减少我们获取连接所消耗的…

unpooled与pooled

unpooled每次都是重新获取一个连接&#xff0c;底层源码如下 pooled去判断有没有&#xff0c;有就拿出来用&#xff0c;没有就创建新的&#xff0c;每次用完再还回去 mybatis poolde连接池原理 先去看空闲的有没&#xff0c;有就直接用&#xff0c;没有就去活动连接池里把最老…

.NET性能优化-推荐使用Collections.Pooled

简介 性能优化就是如何在保证处理相同数量的请求情况下占用更少的资源&#xff0c;而这个资源一般就是CPU或者内存&#xff0c;当然还有操作系统IO句柄、网络流量、磁盘占用等等。但是绝大多数时候&#xff0c;我们就是在降低CPU和内存的占用率。 之前分享的内容都有一些局限性…

使用 TFDConnection 的 pooled 连接池

使用 TFDConnection 的 pooled 连接池 从开始看到这个属性&#xff0c;就一直认为他可以提供一个连接池管理功能&#xff0c; 苦于文档资料太少&#xff0c; 甚至在帮助中对该属性的使用都没有任何介绍&#xff0c;如果你搜索百度&#xff0c;也会发现基本没资料。 最后终于在…

Mybatis 连接池POOLED

1、连接池&#xff1a; 我们在实际开发中都会使用连接池。 因为它可以减少我们获取连接所消耗的时间。 2、mybatis中的连接池 在 Mybatis 中也有连接池技术&#xff0c;但是它采用的是自己的连接池技术。 在 Mybatis 的 SqlMapConfig.xml 配置文件中&#xff0c;通过来实 现 My…

Mybatis连接池介绍与分类 Mybatis使用POOLED UNPOOLED配置连接池的原理分析

一、连接池 1.概念&#xff1a;其实就是一个容器&#xff08;集合&#xff09;&#xff0c;存放数据库连接的容器。 当系统初始化好后&#xff0c;容器被创建&#xff0c;容器中会申请一些连接对象&#xff0c;当用户来访问数据库时&#xff0c;从容器中获取连接对象&#xf…

阶段3 1.Mybatis_07.Mybatis的连接池及事务_3 mybatis连接池的分类

2、mybatis中的连接池 mybatis连接池提供了3种方式的配置&#xff1a; 配置的位置&#xff1a; 主配置文件SqlMapConfig.xml中的dataSource标签&#xff0c;type属性就是表示采用何种连接池方式。 type属性的取值&#xff1a; POO…

Monkey Test简单介绍

什么是Monkey Test&#xff1f;顾名思义&#xff0c;就像一只猴子一样&#xff0c;它的下一步具有随机性。所以Monkey Test可以简单地理解为动作随机性测试&#xff01; Monkey是android模拟器或设备上运行的一个程序。它可以生成伪随机用户事件&#xff08;例如点击、触碰或滑…

monkey工具详解

第一部分&#xff1a;背景 1.为什么要开展压力测试&#xff1f; 提高产品的稳定性 提高产品的留存率 2.什么时候开始压力测试&#xff1f; 首轮功能测试通过后 下班后的夜间进行 第二部分&#xff1a;理论 1.什么是monkey&#xff1f; Monkey是发送伪随机用户事件的工…

monkey的基本使用

一、monkey介绍 1.功能&#xff1a;采用伪随机测试的方式&#xff0c;来完成app的稳定性测试 2.执行原理&#xff1a;通过monkey的shell脚本去执行安卓系统中自带的monkey.jar工具 3.通常用于盲测&#xff0c;压力测试和冒烟测试 1&#xff09;盲测&#xff1a;忽略功能和业务逻…

Monkey使用详解

App monkey 使用篇 安装包下载&#xff1a; 下载mumu模拟器地址&#xff1a;http://mumu.163.com/baidu/ 下载adb安装包 地 址&#xff1a;http://www.downza.cn/soft/219906.html Adb环境变量 配 置&#xff1a;在path里新建adb安装路径即可。 cmd 打开命令提示符窗口输入&a…

monkey的基本定义及基本使用(菜鸟学习中)

一.monkey的定义 1.(转自 https://blog.csdn.net/beyond_f/article/details/78543070 ) Monkey程序由Android系统自带&#xff0c;使用Java语言写成&#xff0c;在Android文件系统中的存放路径是&#xff1a;/system/framework/monkey.jar&#xff1b; Monkey.jar程序是由一…

Android测试--monkey详细到炸的总结

一、Monkey简介&#xff1a; Monkey是Android中的一个命令行工具&#xff0c;可以运行在模拟器里或者现实设备中&#xff0c;向系统发送伪随机的用户事件流&#xff08;点击、滑动、Application切换、横竖屏、应用关闭&#xff09;实现对正在开发的应用程序进行压力测试。monk…

APP稳定性测试利器 Monkey介绍、实战使用、日志分析

第一、Monkey简介 Monkey是什么&#xff1f; Monkey 是安卓官方提供的一个命令行工具&#xff0c;可以运行在Android模拟器和实体手机上。通过Monkey 来模拟用户的触摸、点击、滑动、系统按键的操作&#xff0c;来对APP进行压力测试、稳定性测试。换句话说&#xff0c;就是在乱…

Clumsy弱网、丢包测试工具

一、下载clumsy安装包&#xff0c;解压后打开clumsy.exe 二、ping www.baidu.com查看是否模拟成功 三、pc端模拟丢包和网络延迟 四、APP端模拟丢包和网络延迟 1.手机连接抓包工具charles 2.打开clumsy&#xff0c;在过滤器filtering中输入outbound and ip.DstAddr 192.168.…

【弱网】clumsy的filter语法设置

clumsy 官方说明 jagt WinDivert 的语法 https://github.com/basil00/Divert/wiki/WinDivert-Documentation#7-filter-languageDivert大神们的改版 clumsy-regoutbound 发送 inbound

弱网测试工具clumsy

clumsy 能在 Windows 平台下人工造成不稳定的网络状况&#xff0c;方便你调试应用程序在极端网络状况下的表现。 简介 利用封装 Winodws Filtering Platform 的WinDivert 库, clumsy 能实时的将系统接收和发出的网络数据包拦截下来&#xff0c;人工的造成延迟&#xff0c;掉包…

使用clumsy模拟网络延迟

为何模拟网络延迟 由于最近打算做及时对战类的游戏&#xff0c;对于及时对战类的游戏&#xff0c;首先要解决的问题就是网络延迟的问题。网络延迟对于游戏的体验至关重要。那么开发一款网络游戏要怎么解决这一问题呢。想要解决网络延迟&#xff0c;首先就要模拟网络延迟。那么…