一、问题现象

1.现象:

页面上所有对数据库的操作都无法进行,程序连接池跑满。

2.应用侧报错如下:

Caused by: java.sql.SQLException: [1388d8fe714001-1][10.0.*.*:3306][saas]ERR-CODE: [TDDL-4614][ERR_EXECUTE_ON_MYSQL] Error occurs when execute on GROUP 'SAAS_DB_*_WXET_0*' ATOM 'rm-*_saas_db_qac2_0000': wait millis 5000, active 100, maxActive 100, creating 0 
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:998)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3835)
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3771)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435)

3.数据库现象:

出现大量 Waiting for table metadata lock  锁等待

锁占用mysql_mysql

二、执行操作

ALTER TABLE dj_fwqxx ADD COLUMN skply varchar(10) CHARACTER SET gbk COLLATE gbk_chinese_ci comment '税控盘来源'

三、问题复现

1、同一个数据库中,开启三个会话。

2、在第一个会话中开启一个显示事务,并且执行一条dml语句,模拟应用侧操作。

begin;
INSERT INTO `sk_lock`.`dj_fwqxx` (`id`, `jqbh`, `ipdz`, `dkh`, `fwqlx`, `fwqxh`, `fwqrl`, `fplxdm`, `qybz`, `fwqbm`, `fwqbbh`, `kpdwdm`, `kpdwmc`, `swjgdm`, `swjgmc`, `sldz`, `sldkh`, `kpjh`, `zcm`, `zcm_qsrq`, `zcm_zzrq`, `zcm_num`, `app_url`, `app_state`, `prov`, `ORG_ID`, `TENANT_ID`, `dqsz`, `qysj`, `qylx`, `blxx`, `qtkzxx`, `gzzt`, `jkkzzt`, `sbzskl`, `cpyxgsl`, `locations`, `lasttimes`, `czfs`, `pzid`, `bsipdz`, `bsdkh`, `tqm`, `ptbs`, `dxfwqybz`, `mac`, `bz`, `falg`, `zs`, `usb`, `xfbs`) VALUES ('0000724c-1a06-4ce9-969e-7449827f9b36', '53990****', 'j****.org', '60**', '1', '', '0', '004,007,', 'Y', '5399****', '', '913****', '常州******', '132******', '常州************', 'fpsc.j******', '******', '0', NULL, NULL, NULL, NULL, 'http://******', 'Y', '江******', NULL, NULL, '202******', '201******', '00', '00******', '', '', NULL, '12345678', NULL, NULL, NULL, NULL, '084ffd51-b714-48d******3', 'bswj.j******', '9001', NULL, NULL, NULL, '', NULL, '是', '是', NULL, NULL);

3、在第二个会话中中进行ddl操作

ALTER TABLE dj_fwqxx ADD COLUMN skply varchar(10) CHARACTER SET gbk COLLATE gbk_chinese_ci comment '税控盘来源'

4、在第三个会话中查看线程状态

出现源数据锁

锁占用mysql_数据库_02

四、问题分析

1、Meta Lock锁出现的三种情况。

1、大查询或mysqldump导致alter等待MDL
2、表上存在未提交的事务,导致alter等待MDL
3、存在一个查询失败的语句,比如查询不存在的列,语句失败返回,但是事务没有提交,此时alter仍然会被堵住。

2、问题定位

在对该表执行DDL语句时,正好有DML语句对该表进行操作,由于DDl语句已经进行了表结构修改,导致DML语句处于一个即未提交,也未回滚的状态(猜测应用侧对这种情况没有进行处理
所以就会一直出现meta lock,后续所有进来的sql,也就会出现waiting lock ,而由于这个表使用比较频繁,很快就导致 Proxy 到实际 db的连接池被打满,
也就出现了 "wait millis 5000, active 100, maxActive 100",而应用侧整体连接数大于 Db,也就出现了程序重启后无法连接到数据库。

五、问题解决

方案一、查找到导致阻塞的事务,杀掉对应线程。

select * from information_schema.innodb_trx

kill 对应线程号

方案二、终止DDL语句,选择业务低峰期或其他时间段执行。

#
show PROCESSLIST #找到对应的ddl语句,kill掉 对应的进程id


#注意:
数据库在执行该操作时,需要考虑表是否进行分库分表,如果表进行了分库分表,可能会导致出现数据不一致情况,
如分库分表出现元数据库锁,切忌不可在实际rds进行kill操作。