Technicalarticles

MySQL表自增id溢出的故障复盘,你是如何解决与监控的
作者:赵刘伟 时间:2020-08-18 浏览量:

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

背景:

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


处理过程:

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


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


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



只需要下面几步:

use logdb;

select max(idfrom tb1;  -- 记录下当前最大的id为 xxxx
create table tb2 LIKE tb1;  -- 创建影子表

alter table tb2 modify column id bigint unsigned not null auto_increment ;  -- 修改新表为bigint unsigned类型,能存 18446744073709551615 行数据。
alter table tb2 auto_increment=xxxx+1-- 改大新表的自增主键起始值

rename table tb1 to tb_archive , tb2 to tb1; -- 切换表名

这样操作后,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(2CASE data_type
   WHEN 'tinyint'  THEN 7
   WHEN 'smallint' THEN 15
   WHEN 'mediumint' THEN 23
   WHEN 'int'    THEN 31
   WHEN 'bigint'  THEN 63
   END+(column_type LIKE '% unsigned'))-1 AS max_int 
  FROM information_schema.tables t
   JOIN information_schema.columns c USING (table_schema,table_name)
  WHERE
   c.extra = 'auto_increment' 
  AND
   t.TABLE_SCHEMA NOT IN ('information_schema','mysql''sys','test','performance_schema'
  AND
   t.auto_increment IS NOT NULL ;



01.png

在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

02.png


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

03.png

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

返回列表

想和你做个朋友

DO U LIKE?