在实际的开发中,一般都会将数据存储到数据库中,在设计表的时候,其实id如果达到最大值的话,会出现什么问题。其实主要分两种情况,一种是设置了主键id,另一种没有设置主键id。
表定义自增值id
create table test(id int unsigned auto_increment primary key) auto_increment=4294967295;
insert into test values(null);
我们创建了一个临时表,id 为 int 无符号 。范围在 0 到4,294,967,295。当时当我们在次插入一条记录的时候,1062 - Duplicate entry '4294967295' for key 'test.PRIMARY', Time: 0.000000s
直接返回了异常,抛出的是 4294967295 重复,可以得处的结论是 在申请下一个id时,得到的值保持不变,但是会主键冲突。
从业务层面考虑,其实单表撑到千万级别 性能就开始下降,所以很难达到十亿级别。
InnoDB系统自增 row_id
另一种情况就是没有指定主键,innoDB会创建一个不可见的,长度为6个字节的row_id , 维护一个全局的dict_sys.row_id值,所有无主键的表,每插入一行数据,将dict_sys.row_id 作为要插入的row_id,然后将row_id 值加1。
当时如果出现row_id = N的行,那么就会出现数据覆盖。
面试官:数据库自增 ID 用完了会咋样?
row_id 达到最大值后会从 0 重新开始算;前面插入的数据就会被后插入的数据覆盖,且不会报错。
所以,结合两种方式来看的话,其实更推荐设置一个逐渐id,因为相比数据丢失 可用性和可靠性,大多数应用,还是优先可靠性。
Xid
redo log和 bin log 配合的时候,会使用xid,用来对应事务。
MySQL 内部维护一个全局变量 global_query_id , 每次执行语句的时候将它赋值给 query_id ,将这个变量+1,如果这个语句是当前事务的第一条语句,就将这个事务 query_id 赋值给这个事务id。
global_query_id 是一个存内存的变量,每次重启就会清零,所以多个mysql实例可能存在相同的Xid, 但是bin log 文件也会重新生成,所以基本上不会出现同一个bin log出现两个相同的Xid
Innodb trx_id
Xid是server层维护的,InnoDB内部使用xid 是为了在Innodb事务和Server之间做关联,innodb自己的trx_id 另外维护。
innoDB内部维护一个max_trx_id 全局变量,每次申请一个trx_id 获取当前值使用,并且+1操作。
InnoDB 数据可见性的核心思想是:每一行数据都记录了更新它的 trx_id,当一个事务读到一行数据的时候,判断这个数据是否可见的方法,就是通过事务的一致性视图与这行数据的 trx_id 做对比
thread_id
thread_id 就是线程id, show processlist第一列就是。
系统保持了一个全局变量 thread_id_counter,每新建一个链接,就将thread_id_counter 赋值给这个新连接的线程变量。达到上限后会重置为0.
总结
所以对于主键id达到上限,就会出现主键冲突异常,但是对于无主键的就会重新设置为0,会覆盖原来的数据。