陈同学
微服务
Accelerator
About
# 手工重现Mysql插入的"2.6亿"垃圾数据 > [SHOW PROCESSLIST Syntax](https://dev.mysql.com/doc/refman/5.7/en/show-processlist.html) > [Examining Thread Information](https://dev.mysql.com/doc/refman/5.7/en/thread-information.html) 本文是昨天 [Mysql插入2.6亿条垃圾数据后会发生什么?](https://chenyongjun.vip/articles/42) 的续篇,将模拟生产环境情况,加深对问题的理解,探索更多解决方式,同时也更多的了解下mysql `kill`命令。 ## 重现准备 基于`Mysql 5.7.22`,在一个事务内,利用存储过程往测试表中插入1千万记录,在此过程中进行`kill mysql thread`、`drop table` 等操作。 测试表和过程对应的SQL可见本文最后的附录。 ## 开始重现 ### 执行存储过程,插入数据 执行存储过程之后,事务中处理的记录数高速增长。 ![](https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/06/11/1278b58fe555422982f4f609a7a3dd82.png) ### 对表执行DDL操作 在上述事务 **inserting** 期间,对表执行 `truncate`、`drop`,通过`show processlist`结果如下: `drop table test` ![](https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/06/11/eafec0ecbf9c4ee08c1bf0c18dd15fa5.png) `truncate table test` ![](https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/06/11/c470c49e98714ab8855af7bc7fd491e9.png) 上面两个操作的结果都是: *Waiting for table metadata lock* > 如果你想了解什么是 Metadata lock,可以查阅官网文档 [Metadata Locking](https://dev.mysql.com/doc/refman/5.7/en/metadata-locking.html) ### kill mysql thread 在插入850W记录后,表容量扩展到1G,CPU和内存被`mysqld`基本耗尽. 现在,kill 下图中 mysql thread **12**,事务进入 **ROLLING BACK** 状态。同时,在`PROCESSLIT`中会发现该线程已消失。 ![](https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/06/11/b21372dd127c4d088d183e2f7817bf74.png) 在 *rollback* 期间,对表做任何DDL操作其实和 *inserting* 期间是一样的。 ### restart mysql 在上述 *rollback* 期间,停止Mysql,再重启。Mysql会继续事务的回滚(ps:其实不用想,这是肯定的,否则无法保障数据一致性需求) ## 理解mysql kill > 参考 [KILL Syntax](https://dev.mysql.com/doc/refman/5.7/en/kill.html) ### kill的使用 每一个连接到 [mysqld](https://dev.mysql.com/doc/refman/5.7/en/mysqld.html) 的 connection都将使用独立的 *thread* 来运行。可以使用 **kill** 命令来杀死thread. 通过 `show processlist` 查看当前线程,下图中的ID字段即 *mysql thread id*. 该命令与查询 *processlist* 表的效果一样 ![](https://blog-1256695615.cos.ap-shanghai.myqcloud.com/2018/06/11/1558c6222e684ca58a62a127cb2674f3.png) **kill** 提供了两个选项: * kill connection:将关闭连接,默认使用该选项。eg: `kill 1` 和 `kill connection 1`效果一样 * kill query:中断当前连接正在执行的SQL,但是连接不会关闭,可以继续使用, eg: `kill query 1` ### kill的原理 使用kill命令处理mysql thread时,将会为这个thread设置一个**kill flag**。在大多数情况下,线程可能需要一些时间才能被killed,因为mysql会以特定的间隔来检查设置了 **kill flag** 的thread并将其kill. 关于kill flag在各种操作期间的检查情况,可以参考 [KILL Syntax](https://dev.mysql.com/doc/refman/5.7/en/kill.html) ## 小结 本文虽然重现了问题的过程,但其实并未解决问题。后续将继续分享以下几个知识点,作为本次事件的续篇。 * kill mysql thread后事务的处理机制? * InnoDB redo/undo机制以实现事务并保障数据的一致性 * redo/undo buffer是如何耗尽内存的? * mysql 常见锁的排查流程 ## 附录 ### 测试表 包含主键和3个普通字段,将使用mysql `uuid() `赋值 ```mysql CREATE TABLE test.test ( id INT(11) NOT NULL AUTO_INCREMENT, uid CHAR(36) DEFAULT NULL, uid2 CHAR(36) DEFAULT NULL, uid3 CHAR(36) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE = INNODB; ``` ### 测试的存储过程 存储过程运行1千万次,在运行过程中将中断执行。 ```mysql CREATE DEFINER = 'test'@'%' PROCEDURE test.test() BEGIN DECLARE i INT; START TRANSACTION; SET i = 1; REPEAT INSERT INTO test (uid, uid2, uid3) VALUES (UUID(), UUID(), UUID()); SET i = i + 1; UNTIL i >= 10000000 END REPEAT; COMMIT ; END ```
本文由
cyj
创作,可自由转载、引用,但需署名作者且注明文章出处。
文章标题:
手工重现Mysql插入的"2.6亿"垃圾数据
文章链接:
https://chenyongjun.vip/articles/43
扫码或搜索 cyjrun 关注微信公众号, 结伴学习, 一起努力