这个项目是我接手某位大仙的,真想把ta供起来,然而这个people我从来没见过也不知道是谁,可能老师知道,不对,他一定知道!(只能从现有网页的最底下logo看到是广州某公司,非常想给它删掉换成我的个人签名。)这也就加大了我的编程难度,无法随意改动大仙的代码,时刻要揣摩大仙的编码意图。以前不知道从哪里看的或者听得一句话,大意就是每个程序猿写出的代码毕竟有ta的意图,不要随意去批评别人的代码,我就怕自己的水平有限误解了大仙的代码,所以一边代码一边小心翼翼的在心里骂ta,只有我再三确定ta的某些代码跟屎一样,我才会大声骂出来。代码基本没有注释我就不说了,每个entity一个Dao我就不说了,错误正常都向用户返回成功的提示我也特么也不说了,数据库表结构设计的我真是第一次见到,理解大仙的代码和思路,三个字:难!难!难!当然肯定有可学习之处,应该是在套其所在神级公司的现有框架,不过以我得水平,觉得好像把spring的有些东西实现了一下,但是这些代码和业务代码高耦合。这个项目本身最大的难点在于数据种类多,复杂,基本都是医学用词,摆在我面前的除了这个,还有大仙留下的一个个坑T T。
一下子没忍住, 好了,进入正题~,项目中用到的技术是html+ajax+servelet+ibatis,这个我没办改变,不可能去重构代码。
先说我我的解决方法:找到锁住的线程然后kill掉。
mysql> kill thread id;
下面我们分析一下。
show processlist查看所有运行的线程,发现所有线程的状态都是sleep,查了下sleep状态大意就是未释放资源,线程正在等待客户端发送新的请求。可能会有疑问为什么没有locked状态,查了下innodb的行锁并不会体现在线程状态中,这样就能解释通明明是锁等待为什么状态是sleep。
mysql> show full processlist; +------+------+---------------------+----------+---------+-------+-------+-----------------------+ | Id | User | Host | db | Command | Time | State | Info | +------+------+---------------------+----------+---------+-------+-------+-----------------------+ | 1172 | root | 112.124.64.64:43083 | eye | Sleep | 12384 | | NULL | | 1179 | root | 112.124.64.64:43086 | eye | Sleep | 596 | | NULL | | 1181 | root | 112.124.64.64:43087 | eye | Sleep | 12467 | | NULL | | 1182 | root | 112.124.64.64:43088 | eye | Sleep | 149 | | NULL | | 1183 | root | 112.124.64.64:43089 | eye | Sleep | 612 | | NULL | | 1184 | root | 112.124.64.64:43090 | eye | Sleep | 39 | | NULL | | 1197 | root | 112.124.64.64:43092 | eye | Sleep | 148 | | NULL | | 1198 | root | 112.124.64.64:43093 | eye | Sleep | 5415 | | NULL | | 1200 | root | 112.124.64.64:43095 | eye | Sleep | 581 | | NULL | | 1289 | root | 58.249.112.63:5657 | eye | Sleep | 1496 | | NULL | | 1325 | root | localhost | NULL | Query | 0 | NULL | show full processlist | +------+------+---------------------+----------+---------+-------+-------+-----------------------+
看information_schema库中的INNODB_TRX表发现有几条记录,时间和用户反馈的时间是对上号的,id号在上结果中也有显示,表列太多,截图没截全:
show engine innodb status发现有以下几行:
---TRANSACTION 17E34B, ACTIVE 3296 sec 2 lock struct(s), heap size 376, 0 row lock(s), undo log entries 15 MySQL thread id 1196, OS thread handle 0x7f1f0759d700, query id 140864 112.124.64.64 root Trx read view will not see trx with id >= 17E34C, sees < 17DFA9 ---TRANSACTION 17E11F, ACTIVE 6222 sec 10 lock struct(s), heap size 3112, 9 row lock(s), undo log entries 11 MySQL thread id 1199, OS thread handle 0x7f1f07458700, query id 140844 112.124.64.64 root Trx read view will not see trx with id >= 17E120, sees < 17DFA9 ---TRANSACTION 17DFAA, ACTIVE 11653 sec 2 lock struct(s), heap size 376, 0 row lock(s), undo log entries 15 MySQL thread id 1178, OS thread handle 0x7f1f0af75700, query id 133760 112.124.64.64 root Trx read view will not see trx with id >= 17DFAB, sees < 17DFA7 ---TRANSACTION 17DFA9, ACTIVE 11655 sec 3 lock struct(s), heap size 376, 1 row lock(s), undo log entries 15 MySQL thread id 1177, OS thread handle 0x7f1f1b682700, query id 133743 112.124.64.64 root Trx read view will not see trx with id >= 17DFAA, sees < 17DFA7 ...... ROW OPERATIONS -------------- 0 queries inside InnoDB, 0 queries in queue 5 read views open inside InnoDB Main thread process no. 27675, id 139771259049728, state: waiting for server activity Number of rows inserted 3158, updated 834, deleted 113, read 34640784364 0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
不是特别理解"MySQL thread id 1196, OS thread handle 0x7f1f0759d700, query id 140864 112.124.64.64 root
Trx read view will not see trx with id >= 17E34C, sees < 17DFA9",Trx read view will not see trx是指事务找不到还是connection 找不到了还是咋的?"undo log entries 15"的意思是15条没有insert进去,还是回滚操作没有回滚回来?ROW OPERATIONS下面的
state: waiting for server activity Number of rows inserted 3158, updated 834, deleted 113, read 34640784364
怎么从这个中找到有用信息,让我知道哪些语句操纵哪些表哪些行时出了问题,3158,834这些数字能给人什么提示?希望以后有机会让大神看到这篇博客帮我解惑。
查找过程中看到某博客mysql 执行状态分析 show processlist中一段“实战范例:因前端数据输出时(特别是输出到用户终端)未及时关闭数据库连接,导致因网络连接速度产生大量sleep连接,在网速出现异常时,数据库too many connections挂死。简单解读,数据查询和执行通常只需要不到0.01秒,而网络输出通常需要1秒左右甚至更长,原本数据连接在0.01秒即可释放,但是因为前端程序未执行close操作,直接输出结果,那么在结果未展现在用户桌面前,该数据库连接一直维持在sleep状态!”这段话说“因为前端程序未执行close操作,直接输出结果,那么在结果未展现在用户桌面前,该数据库连接一直维持在sleep状态”,我不太懂,为什么等到结果展现给用户后才close操作,一般不都是把数据查上来(这个时候链接是释放了的)才在service层处理,之后才通过control层返回给浏览器呈现。
我觉得这次MySQL出现这个问题很可能因为网络原因,用户等不急返回结果,关掉了插入数据操作的modal框,又点击添加,打开一个新的模态框操作同一患者的信息导致的。但是我的service层的每次操作是手动开启手动关闭事务的,看了ibatis源码,事务完成后会关闭链接session,为什么还会出现长时间等待?而且好像对之后的其他行数据操作也产生了影响,其他事务操作的是不同行数据,难道因为查询时需要全表扫描导致所有事务等死了?
public void endTransaction() throws SQLException { try { getLocalSqlMapSession().endTransaction(); } finally { getLocalSqlMapSession().close(); } }
世行无难事,只怕有心人,以上的所有疑问总有一天肯定会全部清除的,之后也会记录下供大家学习~