前段时间做一个后台系统,在开发测试环境应用运行的非常良好,没有出现任何的问题。
当测试完成上预发布时问题出现了,应用运行非常缓慢,一直停在某一个地方不执行,最后抛一个nested exception is java.sql.SQLException: 关闭的连接的异常,很时郁闷。刚开始碰到这个部题一直以为是我的连接池出现了问题,应用中事务太大,导致死锁等引起的。
网上也搜了一个遍,找到的答案基本都是说连接池配制有误,我用的C3P0的连接池,DB用的是oracle的,但一遍遍查应用,检查连接池配制,把超时设的很长各种方法都用尽了,最后还是不OK!
最后居然怀疑事务太大,所以就把设计做了变更,开发测试都没问题,但一上线,运行结果还是一样的问题,一度限入了僵局,难道是DB出现了问题?开发库测试库都是OK的。只能把问题定义到DB上去了
用select object_name,machine,s.sid,s.serial#
from v$locked_object l,dba_objects o ,v$session s
where l.object_id = o.object_id and l.session_id=s.sid;
查了一下数据库,发现有张表未做提交,可会话已结束,这就是应用已死提,对数据库操作未做提交!奇怪。。
没办法,只能开始慢慢查询,非常简单,我把应用启动起来,然后让DBA在DB上观看一下执行计划,问题找到了。
DBA回复:
delete from table_name where id = :1 ;
这条SQL走错了执行计划,用了全表扫描引起的。
今天在测试库发现SQL执行计划:
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 61 | 2161 (1)| 00:00:26 |
| 1 | DELETE | table_name | | | | |
|* 2 | TABLE ACCESS FULL| table_name | 1 | 61 | 2161 (1)| 00:00:26 |
------------------------------------------------------------------------------------------
分析表上的统计信息后走上了正确的执行计划:
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | 1 | 58 | 1 (0)| 00:00:01 |
| 1 | DELETE | table_name | | | | |
|* 2 | INDEX UNIQUE SCAN| table_name _UK | 1 | 58 | 1 (0)| 00:00:01 |
这个问题主要原因是表上频繁的插入删除,数据量的变化造成表上的统计信息陈旧,SQL未能用到正确的执行计划。
防止这个问题的方法有两种:
1.定时分析数据库中表的统计信息。(无需修改SQL,但需要数据库中增加JOB,并且确定分析的周期)
2。对SQL加hints固定执行计划。(修改SQL,但可保证无论何时均可以走到这个S_REAL_BIDWORD_COST_UK索引扫描)
第一种方法如果分析周期内数据量出现急剧变化仍会出现走错执行计划的风险,个人建议采用第二种,修改SQL如下:
delete /*+ index(a table_name _UK )*/ from table_name a where a.ID = :1 ;
SQL走错执行计划的问题解释一下:
1.这个跟是否创建了唯一索引是没有关系的。
2. 插入删除频度跟SQL走错执行计划是没有必然联系的。只能说插入删除较多的表,数据量变化很快,更容易出现这样的风险
就算插入删除操作很少的表,但某一天数据量急剧变化的情况(比如平日20W左右的数据量,某时批量插入了200w),也有可能会导致执行计划错误。
3.SQL走错执行计划跟SQL本身是没有关系,SQL的执行计划是由ORACLE内部算法生成(RBO,CBO),同一SQL可能拥有多个执行计划,ORACLE会根据表,索引等的信息来选择使用哪一个执行计划。比如某张表原来只有10条记录,ORACLE会认为走全表扫描会优于索引扫描,但当表记录变化到10w,可能走索引更快。
4。是否定时更新表上的统计信息就能解决这个问题呢?这一直是个争论的话题。官方也未有明确说法,所以这个风险在目前网站各个数据库都存在的,我们目前的解决方案是只对遇到问题表进行分析(已准备在11g的数据库上尝试由ORACLE定时任务去分析)
5.由于这个问题不确定性,性能测试其实是无法规避这个风险的。
6.我们这样做可以最大程度减小这个问题带来的风险:
1。关注数据量巨大的表。(目前和预计增长很快的表)
2。关注数据量变化较大的表(比如插入,删除频繁,有批量删除插入的表)
3。关注SQL性能要求很高的SQL(执行频率很高的SQL)
总的说来这个问题不是程序BUG,不是SQL本身的问题,无法验证,其实也很难模拟重现。呵…毕竟ORACLE也是人写的程序没有那么十全十美,所以DBA每次新项目上线都会很关注是否有新的TOP SQL,偶尔会发现这样的问题,对需要关注的表和SQL大家做好沟通能最大程度减小这个风险。
分享到:
相关推荐
java.sql.SQLException: 不支持的字符集 (在类路径中添加 orai18n.jar): ZHS16GBK ……
在Java编程中,`java.sql.SQLException: 结果集已耗尽` 是一个常见的错误提示,通常出现在处理数据库查询结果集时。这个异常表明程序试图访问已经没有数据的结果集中下一行,即所有行已经被遍历完,尝试访问超出范围...
主要给大家介绍了关于MySQL存储表情时报错:java.sql.SQLException: Incorrect string value: 'xF0x9Fx92xA9x0Dx0A...'的解决方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
1. **共享池(Shared Pool)**:用于缓存最近执行的SQL语句和数据定义,包括库缓存和数据字典缓存。 2. **数据缓冲区(Database Buffer Cache)**:缓存从数据文件中检索的数据块,显著提升读写性能。 3. **日志缓冲...
2. **修改Java连接URL**:在IDEA中,你需要修改数据库连接的URL,添加`serverTimezone`参数。例如,如果你的数据库服务器位于上海,你可以将URL改为`jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=...
### 解决Java_heap_space问题:深入理解与策略 在Java应用程序开发与运行过程中,经常会遇到一个常见的内存管理问题——“Java heap space”。这个问题通常表现为Java虚拟机(JVM)在执行过程中因可用堆内存不足而...
DBCP(Database Connection Pool)是Apache的一个开源项目,提供了一个基于Java的数据源连接池实现。在上述问题中,应用程序遇到了由于连接池不合理的锁机制导致的连接耗尽问题,表现为无法从连接池获取新的数据库...
Caused by: java.sql.SQLException: com.mysql.jdbc.Driver at com.alibaba.druid.util.JdbcUtils.createDriver ...... Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver at java.net....
nested exception is java.sql.SQLException: Access denied for user ‘root’@‘localhost’ (using password: YES) spring boot中使用mybatis连接mysql数据库时报如上错误,确认配置文件中的密码没问题,但是...
nested exception is java.sql.SQLException: Table '.\discuz\cdb_threads' is marked as crashed and should be repaired ``` #### 错误原因分析 此错误出现的原因主要有以下几点: 1. **意外关闭**:如果MySQL...
Java 知识点 Part21 主要涵盖了 MySQL 数据库中的两种引擎 InnoDB 和 MyIASM 的比较、SQL 查询技巧、Java 异常处理以及事务管理的相关概念。下面将逐一详细阐述这些知识点。 1. **MySQL 引擎对比**: - **InnoDB**...
接下来,我们来看Java代码部分是如何调用上述XML配置中的SQL语句的。 ```java public Aa selectAAandSex(int aid) { Aa a = new Aa(); try { a = (Aa) s.queryForObject("selectAAandSex", aid); } catch ...