MySQL表自增id溢出的故障复盘,你是如何解决与监控的

问题:MysqL某个表自增id溢出导致某业务block

背景:

tokudb引擎的一个大表tb1,存放业务上的机审日志,每天有大量的写入, 并且由于历史原因,这张表是int signed 类型的,最大只能存 2147483647行记录 。

处理过程:

增加DBLE中间件代理,然后做range分区,将新数据写到新加的的一个分片上。同时业务上修改连接将这个表tb1的连接方式改走DBLE。

但是业务上改完代码后,发现还有残余的部分insert into tb1的写请求被转发到了老表上,且有些表被错误得路由到了DBLE上。 最终业务上将这个写tb1的代码下线后,整个业务才恢复正常。

后来复盘后,想了下其实这种情况下,对于日志类的表的问题,DBA应该采用迅速果断的措施 尽快恢复业务,然后再考虑其它问题。这样考虑的话,上面的问题就好解决了。

只需要下面几步:

uselogdb;

selectmax(id)fromtb1;--记录下当前最大的id为xxxx

createtabletb2LIKEtb1;--创建影子表

altertabletb2modifycolumnidbigintunsignednotnullauto_increment;--修改新表为bigint unsigned类型,能存 18446744073709551615 行数据。

altertabletb2auto_increment=xxxx+1;--改大新表的自增主键起始值

renaMetabletb1totb_archive,tb2totb1;--切换表名这样操作后,tb1就可以写入数据了,业务也能暂时恢复,剩下的工作就是把 tb_archive 表的数据迁移到 tb1 里面的(迁移数据可以使用pt-archiver工具在后台慢慢跑就行)。

整个操作中切表最多5分钟左右即可恢复业务的写入操作,剩余的迁移数据的影响相对会小一些。

增加对自增id的监控

由于疯狂的写系统日志数据,造成主键值溢出的情况出现,因此有必要将这个指标监控起来。

MysqLd_exporter自带的这个功能,下面是我使用的启动参数:

nohup ./MysqLd_exporter --config.my-cnf="./my.cnf" --web.listen-address=":9104" --collect.heartbeat --collect.auto_increment.columns --collect.binlog_size --collect.engine_innodb_status --collect.engine_tokudb_status --collect.slave_hosts --collect.slave_status --collect.info_schema.processlist --collect.info_schema.innodb_metrics > /dev/null 2>&1 &

实际上执行的类似这个sql

SELECT

table_schema,

table_name,

column_name,

AUTO_INCREMENT,

POW(2,CASEdata_type

WHEN'tinyint'THEN7

WHEN'smallint'THEN15

WHEN'mediumint'THEN23

WHEN'int'THEN31

WHEN'bigint'THEN63

END+(column_typeLIKE'%unsigned'))-1ASmax_int

FROM@R_8_4045@ion_schema.tablest

JOIN@R_8_4045@ion_schema.columnscUSING(table_schema,table_name)

WHERE

c.extra='auto_increment'

AND

t.TABLE_SCHEMAnotin('@R_8_4045@ion_schema','MysqL','sys','test','performance_schema')

AND

t.auto_incrementISNOTNULL;

在prometheus的web界面,我们可以测试编写如下的promql, 找出剩余自增id可以率少于40%的实例的库+表名

(MysqL_info_schema_auto_increment_column_max{schema!~'test|MysqL'} - MysqL_info_schema_auto_increment_column{schema!~'test|MysqL'})/MysqL_info_schema_auto_increment_column_max{schema!~'test|MysqL'}*100 < 40

取到数据后,我们可以在alertmanager里面配置相关的告警,或者再grafana上面绘制图,如下:

整理些生产上可能遇到的突发问题,并正对性的制定相关的应急预案

相关文章

MySQL 死锁 是指两个或多个事务互相等待对方持有的锁,从而导...
在MySQL中,InnoDB引擎通过Next-Key Locking技术来解决幻读问...
在数据库事务管理中,Undo Log 和 Redo Log 是两种关键日志,...
case when概述 sql语句中的case语句与高级语言中的switch语句...
其实很简单,只是为了忘记,做个记录,用的时候方便。 不管是...
1.进入服务,找到mysql服务,在属性里找到mysql的安装路径 2...