正文
t
values
(
null
,
1
,
1
);
流程图如下所示
流程步骤:
-
AUTO_INCREMENT=1
(表示下一次插入数据时,如果需要自动生成自增值,会生成 id=1。)
-
insert into t values(null, 1, 1)
(执行器调用 InnoDB 引擎接口写入一行,传入的这一行的值是 (0,1,1))
-
get AUTO_INCREMENT=1
(InnoDB 发现用户没有指定自增 id 的值,获取表 t 当前的自增值 1 )
-
AUTO_INCREMENT=2 insert into t values(1, 1, 1)
(将传入的行的值改成 (1,1,1),并把自增值改为2)
-
insert (1,1,1)
执行插入操作,至此流程结束
大家可以发现,在这个流程当中是先进行自增值的+1,在进行新增语句的执行的。大家可以发现这个操作并没有进行原子操作,如果SQL语句执行失败,那么自增是不是就不会连续了呢?
三、自增主键值不连续情况:(唯一主键冲突)
当我执行以下SQL语句时
insert into t values(null, 1, 1);
第一次我们可以进行新增成功,根据自增值的修改机制。如果插入数据时 id 字段指定为 0、null 或未指定值,那么就把这个表当前的
AUTO_INCREMENT
值填到自增字段;
当我们第二次在执行以下SQL语句时,就会出现错误。因为我们表中c字段是唯一索引,会出现
Duplicate key error
错误导致新增失败。
例如:
-
AUTO_INCREMENT=2
(表示下一次插入数据时,如果需要自动生成自增值,会生成 id=2。)
-
insert into t values(null, 1, 1)
(执行器调用 InnoDB 引擎接口写入一行,传入的这一行的值是 (0,1,1))
-
get AUTO_INCREMENT=2
(InnoDB 发现用户没有指定自增 id 的值,获取表 t 当前的自增值 2 )
-
AUTO_INCREMENT=3 insert into t values(2, 1, 1)
(将传入的行的值改成 (2,1,1),并把自增值改为3)
-
insert (2,1,1)
执行插入操作,由于已经存在 c=1 的记录,所以报
Duplicate key error
,语句返回。
可以看到,这个表的自增值改成 3,是在真正执行插入数据的操作之前。这个语句真正执行的时候,因为碰到唯一键 c 冲突,所以 id=2 这一行并没有插入成功,但也没有将自增值再改回去。所以,在这之后,再插入新的数据行时,拿到的自增 id 就是 3。也就是说,出现了自增主键不连续的情况。
四、自增主键值不连续情况:(事务回滚)
其实事务回滚原理也和上面一样,都是因为异常导致新增失败,但是自增值没有进行回退。
五、自增主键值不连续情况:(批量插入)
批量插入数据的语句,MySQL 有一个批量申请自增 id 的策略:
-
语句执行过程中,第一次申请自增 id,会分配 1 个;
-
1 个用完以后,这个语句第二次申请自增 id,会分配 2 个;
-
2 个用完以后,还是这个语句, 第三次申请自增 id,会分配 4 个;
-
依此类推,同一个语句去申请自增 id,每次申请到的自增 id 个数都是上一次的两倍。
执行以下SQL语句(在表t中先新增了4条数据,在创建表tt把表t数据进行批量新增)