记一次auto_increment引发的悲剧

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

实战

先来看看架构图吧

  1. x表将数据写入A,这时候A的id是自增长的
  2. A再将自己的自增长的id(发号器),写入到 B, 注意是指定id写入。insert into B(id) values(xx);
  3. 同时也将数据写入到C

step1

最终的想法是这样的

  1. 主表A将发号器id写入C (id 在一个小区间增长: 1 ~ 100000)
  2. 主表B将发号器id也写入C (id 在一个大区间增长: 10000000 ~ ? )
  3. 很多人疑惑的是:为什么一开始id不区分开来呢? 因为一开始业务没有拆分,需要保证A,B一致。直到某个阶段,才将B设置alter table B auto_increment = 10000000
  4. 这个时候,由于指定id写入的原因,A,B的id还是一致的,直到X表分发数据到不同表。如:xx写入A,yy写入B,这个时候由于A,B的auto_increment不一样,所以id就会有所区分(A的id自增长在小的区间,B的id自增长在大的区间)。

step2

错误场景重现

那么问题就来了,如果这时候B的auto_incrememt再次变回到小区间1 ~ 100000,会导致什么问题呢?
问题严重啦: 这时候由于A,B 都往C表写同一个区间的数据,会导致很多脏数据,结果就悲剧了咯。。。
真实场景重现如下

step3

分析

问题的关键处在auto_increment变小

那么什么场景下回导致auto_increment变小呢?

  1. 参考: http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-handling.html
  2. alter table xx auto_increment = yy;
  3. truncate table
  4. restart mysql
* If you specify an AUTO_INCREMENT column for an InnoDB table, the table handle in the InnoDB data dictionary contains a special counter called the auto-increment counter that is used in assigning new values for the column. This counter is stored only in main memory, not on disk.

To initialize an auto-increment counter after a server restart, InnoDB executes the equivalent of the following statement on the first insert into a table containing an AUTO_INCREMENT column.

SELECT MAX(ai_col) FROM table_name FOR UPDATE;

* A server restart also cancels the effect of the AUTO_INCREMENT = N table option in CREATE TABLE and ALTER TABLE statements, which you can use with InnoDB tables to set the initial counter value or alter the current counter value.

解决方案

  1. 手动插入一条数据到B,让其最大值在10000000+1, 这样就不会出问题。

第二种奇葩问题

  1. 一张刚创建的innoDB表,目前自增是1.
  2. 插入3条记录后,auto_increment=4.
  3. 然后再删除掉这三条记录,auto_increment=4 没变
  4. 关闭MySQL,当MySQL再次起来的时候,会发现auto_increment值从4,变成1

总结

业务不要依赖auto_increment值,它并不是总是递增

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4天前
|
关系型数据库 MySQL Linux
AUTO_INCREMENT
AUTO_INCREMENT
12 2
|
存储 SQL 关系型数据库
MySQL 主键自增 Auto Increment用法
MySQL 主键自增 Auto Increment用法
185 0
|
SQL 关系型数据库 MySQL
Auto-increment 会在新记录插入表
Auto-increment 会在新记录插入表
72 0
|
SQL 关系型数据库 MySQL
MySQL 使用 AUTO_INCREMENT 关键字
MySQL 使用 AUTO_INCREMENT 关键字
103 0
|
SQL 关系型数据库 MySQL
AUTO INCREMENT 字段
AUTO INCREMENT 字段
62 0
|
SQL 关系型数据库 MySQL
记一次MySQL AUTO_INCREMENT的故障
MySQL如果在指定id 进行插入的时候,如果这个id大于表的自增值,那么MySQL会把表的自增值修改为这个id,并加1,但是如果我们把主键更新成更大的值,MySQL并不会把表的自增值修改为更新后的值,会埋下一颗定时炸弹,在某些情况下,如DDL,重启等之后,业务开始报错,会误认为DDL或者重启导致业务表的插入故障。
3281 0
|
关系型数据库 索引
|
关系型数据库 索引