8000 45 | 自增id用完怎么办? · Issue #58 · git-zjx/git-zjx.github.io · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
45 | 自增id用完怎么办? #58
Open
@git-zjx

Description

@git-zjx

表定义自增值 id

表定义的自增值达到上限之后,再申请下一个 id 时,得到的值保持不变

InnoDB 系统自增 row_id

InnoDB 维护了一个全局的 dict_sys.row_id 值,所有无主键的 InnoDB 表,每插入一行数据,都将当前的 dict_sys.row_id 值作为要插入数据的 row_id,然后把 dict_sys.row_id 的值加 1

实际上,在代码实现时 row_id 是一个长度为 8 字节的无符号长整型 (bigint unsigned)。但是,InnoDB 在设计时,给 row_id 留的只是 6 个字节的长度,这样写到数据表中时只放了最后 6 个字节,所以 row_id 能写到数据表中的值,就有两个特征:

  1. row_id 写入表中的值范围,是从 0 到 248-1;
  2. 当 dict_sys.row_id=248时,如果再有插入数据的行为要来申请 row_id,拿到以后再取最后 6 个字节的话就是 0。

也就是说,写入表的 row_id 是从 0 开始到 248-1。达到上限后,下一个值就是 0,然后继续循环。而这样的话,超过上下后就会覆盖之前的数据

Xid

MySQL 内部维护了一个全局变量 global_query_id,每次执行语句的时候将它赋值给 Query_id,然后给这个变量加 1。如果当前语句是这个事务执行的第一条语句,那么 MySQL 还会同时把 Query_id 赋值给这个事务的 Xid

global_query_id 是纯内存变量,重启之后清零,但 MySQL 重启之后也会重新生成新的 binlog 文件,这里也保证了同一个 binlog 文件里 Xid 一定是唯一的

不过 global_query_id 达到上限后,也会从 0 开始计数,但 global_query_id 定义的长度为 8 个字节,这个值很大,可能性微乎其微

Innodb trx_id

InnoDB 内部维护了一个 max_trx_id 全局变量,每次需要申请一个新的 trx_id 时,就获得 max_trx_id 的当前值,然后将 max_trx_id 加 1,max_trx_id 会持久化存储,重启也不会重置为 0,理论上,只要 MySQL 服务运行的足够久,就会出现 max_trx_id 重新从 0 开始的情况,当达到这样一个状态时,就会持续出现脏读的 bug

thread_id

MySQL 保存了一个全局变量 thread_id_counter,每新建一个连接,就将 thread_id_counter 复制给这个新连接的线程变量。

thread_id_counter 定义的大小是 4 个字节,因此达到 232-1 后,它就会重置为 0,然后继续增加

MySQL 在给新线程分配 thread_id 的时候,有如下逻辑:

do {
  new_id= thread_id_counter++;
} while (!thread_ids.insert_unique(new_id).second);

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0