当线程全部为空时,C3P0 明显死锁?
Posted
技术标签:
【中文标题】当线程全部为空时,C3P0 明显死锁?【英文标题】:C3P0 apparent deadlock when the threads are all empty? 【发布时间】:2011-04-13 10:48:32 【问题描述】:我在 Tomcat 中使用 C3P0 作为连接池,我看到非常令人担忧的错误:
2010-09-16 13:25:00,160 [Timer-0] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@43502400 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
2010-09-16 13:25:01,407 [Timer-0] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner - com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@43502400 -- APPARENT DEADLOCK!!! Complete Status:
Managed Threads: 10
Active Threads: 0
Active Tasks:
Pending Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$1RefurbishCheckinResourceTask@6e4151a7
Pool thread stack traces:
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#6,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#5,5,main]
java.lang.Object.wait(Native Method)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:534)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#4,5,main]
java.lang.Object.wait(Native Method)
... many more, exact same stack trace
第 534 行是:
while (true)
Runnable myTask;
synchronized ( ThreadPoolAsynchronousRunner.this )
while ( !should_stop && pendingTasks.size() == 0 )
ThreadPoolAsynchronousRunner.this.wait( POLL_FOR_STOP_INTERVAL ); // <- here
if (should_stop) ...
看起来所有线程都处于空闲状态。他们在等工作。 0 个活动线程,只有 1 个任务要完成。关于出了什么问题的任何线索?
这是配置:
ds.setUser(userName);
ds.setPassword(password);
ds.setMaxPoolSize(16);
ds.setMaxConnectionAge(1800);
ds.setAcquireRetryAttempts(4);
ds.setMaxIdleTime(900);
ds.setNumHelperThreads(10);
ds.setCheckoutTimeout(1000);
【问题讨论】:
您能解决您的问题吗? (我知道已经很久了) @Ittai:不,但它最终消失了。不知道到底是什么修复了它:-( 【参考方案1】:我刚刚遇到了针对 Oracle 数据库的类似问题,但就我而言,Managed Thread
和 Active Thread
的计数相同。
Managed Threads: 3
Active Threads: 3
对我来说,这实际上是一个身份验证错误,但由于我进行登录审核的方式而显示为 APPARENT DEADLOCK
错误。
2013-08-12 11:29:04,910 [Timer-4] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@34996454 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!
2013-08-12 11:29:04,914 [Timer-4] WARN com.mchange.v2.async.ThreadPoolAsynchronousRunner: com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@34996454 -- APPARENT DEADLOCK!!! Complete Status:
Managed Threads: 3
Active Threads: 3
Active Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@6730b844 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@2f91ad49 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@507ac05 (com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1)
Pending Tasks:
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@3aae7ed7
Pool thread stack traces:
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2,5,main]
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(SocketInputStream.java:150)
java.net.SocketInputStream.read(SocketInputStream.java:121)
oracle.net.ns.Packet.receive(Packet.java:300)
oracle.net.ns.DataPacket.receive(DataPacket.java:106)
oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:380)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:760)
oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:401)
oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:546)
oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:236)
oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:521)
com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:134)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#0,5,main]
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(SocketInputStream.java:150)
java.net.SocketInputStream.read(SocketInputStream.java:121)
oracle.net.ns.Packet.receive(Packet.java:300)
oracle.net.ns.DataPacket.receive(DataPacket.java:106)
oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:380)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:760)
oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:401)
oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:546)
oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:236)
oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:521)
com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:134)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
Thread[com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1,5,main]
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(SocketInputStream.java:150)
java.net.SocketInputStream.read(SocketInputStream.java:121)
oracle.net.ns.Packet.receive(Packet.java:300)
oracle.net.ns.DataPacket.receive(DataPacket.java:106)
oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:315)
oracle.net.ns.NetInputStream.read(NetInputStream.java:260)
oracle.net.ns.NetInputStream.read(NetInputStream.java:185)
oracle.net.ns.NetInputStream.read(NetInputStream.java:102)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:124)
oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:80)
oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1137)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:380)
oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:760)
oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:401)
oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:546)
oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:236)
oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:32)
oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:521)
com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:134)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182)
com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171)
com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137)
com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014)
com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32)
com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810)
com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
【讨论】:
好厉害!在进行了一些重大的架构更改后,我遇到了这个错误,所以我认为我搞砸了。真正的原因与您的回答有关——因为我无法通过防火墙进入数据库服务器! 现在有同样的问题。再次因为防火墙规则。 @HankCa 感谢您的领导。 对我来说 100% 正确,aws 安全组。 @HankCa - 你应该发表你的评论作为答案 - 你节省了我几个小时不那么有趣的调试 - 谢谢! @HankCa 我面临同样的问题。一旦记录了问题,它就会不断记录,应用程序响应变得不可预测。我们在aws上,在这种情况下可以采取哪些纠正步骤【参考方案2】:这听起来你已经从池中获取了一个连接,没有及时返回。
C3P0 在获取连接但未在死锁检测超时时间内返回池时确定“明显死锁”。
如果将连接获取移近“动作”并在数据库工作完成后立即将其返回到池中,此消息将消失。
【讨论】:
文档说 setMaxAdministrativeTime 默认为 0(即永远)。此外,为什么我必须在任何固定的时间限制内返回到池的连接?我已经检查过了;只要我需要它就应该是我的……即使不是,这也不是僵局! 你是对的,这就是警告说明显死锁的原因。顺便说一句,你使用了一个连接池,所以你不需要在不使用它的时候保持连接 当然可以,但是有问题的地方可能在一个长期运行的事务中;在此期间您无法释放它。 这应该不会导致问题,根据我的经验,C3P0 检查连接是否被积极使用。我不习惯直接使用 C3P0,我将它与 Hibernate 一起使用 - 但在这种情况下,长事务永远不会成为问题,但空闲连接会导致您收到警告。 刚刚看到您对问题的编辑。您命中的超时由“ds.setMaxIdleTime(900)”设置【参考方案3】:这会解决你的问题
ds.setMaxStatements(1000);
ds.setMaxStatementsPerConnection(100); (the maximum number of prepared statments your system can execute on a single connection)
签出:https://forum.hibernate.org/viewtopic.php?t=947246&highlight=apparent+deadlock+c3p0
完成后记得关闭你的陈述!!
【讨论】:
【参考方案4】:我对答案https://***.com/a/18192588/1019307 的评论收到了足够多的赞成票,表明它应该是一个答案。
我收到此错误是因为我无法通过防火墙访问数据库服务器。请检查这是否是您的问题。
【讨论】:
【参考方案5】:@eebbesen,我遇到了和你一样的错误。我正在运行 Tomcat 9.0.6 版。我的 Maven 项目中有休眠核心版本 5.2.10,休眠 c3p0 版本 3.6.3。我的不是身份验证错误,而是由于我之前更改了计算机的名称。这对 tomcat 没有立即影响,但是在我的机器重新启动后,当我尝试通过 eclipse(Oxygen 2)再次启动 tomcat 时,由于您提出的问题,我无法再启动 eclipse。
我用谷歌搜索了这个,我发现了这个链接,它提示我解决了这个问题:
https://community.oracle.com/thread/339825
上面写着:
先看看OracleServiceXE和OracleXETNSListener服务是否 跑步。将 url 中的 127.0.0.1 替换为您的 IP 或名称 机器。它必须与 tnsnames.ora 文件中声明的主机匹配。
后来它提到在哪里可以找到这个 tnsnames.ora 文件,对我来说它就在这里:
C:\oraclexe\app\oracle\product\11.2.0\server\network\ADMIN
查看这个 tnsnames.ora 文件,我看到了这个:
XE =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = MyMachineName-7)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = XE)
)
)
但我最近将我的机器重命名为 MyMachineName-5。我将 7 更改为 5 并保存了文件。我检查了这个目录中的“listener.ora”文件,它有同样的问题:
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
(ADDRESS = (PROTOCOL = TCP)(HOST = MyMachineName-7)(PORT = 1521))
)
)
我将 7 更改为 5 并保存了文件。
然后我打开任务管理器,单击“服务”选项卡,然后查看“Oracle”服务。我重新启动了:OracleXETNSListener、OracleXEClrAgent、OracleServiceXE。又去eclipse里重启tomcat,这次又出问题了。
附录:
我也用谷歌搜索了这个:
https://community.oracle.com/thread/2267906
这引导我尝试:
1) 在 Windows Defender 中关闭了防火墙(已经关闭了 mcaffee 防火墙)
2) 启动 sqlplus 以确保我可以使用我在休眠文件中使用的凭据登录:hibernate.cfg.xml
C:\oracle\app\oracle\product\11.2.0\server\bin\sqlplus.exe
3) 启动 Oracle Database 11g 的桌面快捷方式
即使我修复了机器名称问题,这对我来说还是失败了,我仍然需要调查。
4) 使用 dbVisualizer,我尝试连接到 Oracle。这仅在我解决了 .ora 文件机器名称问题后才有效:双击连接并单击“ping 服务器”按钮。
【讨论】:
【参考方案6】:我也遇到过同样的问题,但原因有点难以发现,因为它是由一些同时尝试获取连接的资源引起的。
如您所见,如果池尚未初始化,则提供的代码通过调用设置函数来初始化它。
public Connection getConnection() throws SQLException
if (mCPDS == null)
setupPool();
return mCPDS.getConnection();
问题是许多资源在程序开始时试图获取连接,所以一段时间后有多个资源实例化池导致您的问题。
解决方案只是声明方法同步,以在调用该方法时将其他资源排除在外,并且它仍在实例化池中。
public synchronized Connection getConnection() throws SQLException
if (mCPDS == null)
setupPool();
return mCPDS.getConnection();
这可能是不使用单例的设计错误,但解决了缺乏一些性能的问题。
【讨论】:
【参考方案7】:我们遇到了这个问题,并通过将其添加到 C3P0 配置中解决了它:
<property name="statementCacheNumDeferredCloseThreads" value="1"/>
根据:this from the C3P0 doc
【讨论】:
【参考方案8】:通过正确关闭 Statement 和 Resultset 实例(不知何故未关闭)解决了同样的问题(无法检测到):
String SQL = "SELECT 1";
try
con = DriverManager.getConnection(host, userName, userPassword);
stmt = con.prepareStatement(SQL, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
try
rs = stmt.executeQuery(SQL);
try
rs.next();
// ...
finally
rs.close();
finally
stmt.close();
catch (SQLException ex)
Logger.getLogger(MyClass.class.getName()).log(Level.SEVERE, null, ex);
【讨论】:
【参考方案9】:您好,我的朋友只是发表评论,我有同样的情况。我刚刚配置了我的spring-hibernate eclipse项目,出现了同样的异常,需要注意的是我的项目还是没有任何查询。
我通过以下步骤解决了这个问题:
1) 清理项目:项目--> 清理... 2)构建项目:项目-->构建项目
我希望它对你有用。
【讨论】:
【参考方案10】:我突然遇到了同样的问题:在注意到只有在调试模式下启动我的应用程序时才存在死锁(我正在使用 IntelliJ)并且在正常运行时运行良好,我开始挖掘它.
我终于发现一个断点阻塞了连接:我不知道为什么 Intellij 没有“监听”应用程序正在通过那个断点,而是因为断点而被挂在某个地方,这是导致明显的死锁
在我的项目中删除所有断点后,一切又开始顺利。
希望这对某人有所帮助
【讨论】:
【参考方案11】:在 glassfish4 服务器上部署应用程序时遇到了类似的问题。原来这是一个数据库配置问题。只需确保您的数据库连接配置正确,验证配置中提供的主机名是否允许连接到数据库。尝试使用配置的用户名和主机名/域手动连接到数据库。如果需要,允许 db 用户从所需的域进行连接。使用正确的数据库配置重建应用程序,然后部署它。
【讨论】:
以上是关于当线程全部为空时,C3P0 明显死锁?的主要内容,如果未能解决你的问题,请参考以下文章