45 MySQL自增id
45 MySQL自增id
表定义自增id
说到自增id,前面提到mysql的自增id不连续,当表定义的自增值达到上限后的逻辑是:再申请下一个id时,得到的值保持不变
create table t(id int unsigned auto_increment primary key) auto_increment=4294967295;
insert into t values(null);
// 成功插入一行 4294967295
show create table t;
/* CREATE TABLE `t` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4294967295;
*/ insert into t values(null);
//Duplicate entry '' for key 'PRIMARY
2^32-1 不是一个特别大的数,对于一个频繁插入删除数据的表来说,是可能用完的,因此在建表的时候需要观察这个表是否有可能达到这个上限,如果有可能,则需要建成8个字节的bigint unsigned.
--mysql
BIGINT[(M)] [UNSIGNED] [ZEROFILL]
A large integer. The signed range is -9223372036854775808 to 9223372036854775807. The
unsigned range is 0 to 18446744073709551615.
SERIAL is an alias for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE NO_UNSIGNED_SUBTRACTION
By default, subtraction between integer operands produces an UNSIGNED result if any operand
isUNSIGNED. When NO_UNSIGNED_SUBTRACTION is enabled, the subtraction result is signed, even
if any operand is unsigned. For example, compare the type of column c2 in table t1 with that of
column c2 in table t2:
mysql> SET sql_mode='';
mysql> CREATE TABLE test (c1 BIGINT UNSIGNED NOT NULL);
mysql> CREATE TABLE t1 SELECT c1 - 1 AS c2 FROM test;
mysql> DESCRIBE t1;
+-------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------------+------+-----+---------+-------+
| c2 | bigint(21) unsigned | | | 0 | |
+-------+---------------------+------+-----+---------+-------+
mysql> SET sql_mode='NO_UNSIGNED_SUBTRACTION';
mysql> CREATE TABLE t2 SELECT c1 - 1 AS c2 FROM test;
mysql> DESCRIBE t2;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| c2 | bigint(21) | | | 0 | |
+-------+------------+------+-----+---------+-------+
mysql> SET sql_mode = '';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| 18446744073709551615 |
+-------------------------+
mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1 |
+-------------------------+
Innodb系统自增row_id
如果创建的innodb的表没有显式指定主键,那么innodb会创建一个不可见的,长度为6字节的row_id,innodb维护了一个全局的dict_sys.row_id值,所有没有主键的innodb表,没插入一行数据,都将当前的dict_sys.row_id值作为要插入数据的row_id,然后把该值加1.
实际上,在代码实现是row_id是一个长度为8个字节的无符号长整形(bigint unsigned),但是,innodb在设计时,给row_id留的只是6个字节的长度,这样写到数据库表中时只放入了后6个字节,两个特征:
--1 row_id写入表中的范围,0到2^48-1
--2 当dict_sys.row_id=2^48时,如果再有插入数据的行为要来申请row_id,拿到以后再取后6个字节的话就是0,继续循环。
Xid
在答疑文章1中,日志和索引相关问题,介绍了redo log和binlog相配合的时候,提到了它们有一个共同的字段叫做Xid,它在mysql中是用来对应事务的
Mysql内部维护了一个全局变量global_query_id,每次执行语句的时候将它赋值给query_id,然后这个变量加1,如果当前语句是这个事务执行的第一个语句,那么mysql还会同时把query_id赋值给这个事务的xid
而global_query_id是一个纯内存变量, 重启之后就清零了,所以,在同一个数据库实例汇总,不同事务的xid也有可能相同的。
但是mysql重启后,会生成新的binlog文件,这就保证了,同一个binlog文件中,xid是唯一的。
但是如果global_query_id达到上限就会继续从0开始,从理论上讲,就会出现同一个binlog文件中出现相同的xid,因为global_query_id定义的长度是8个字节,上限是2^64-1,理论上回出现这个同一个binlog,相同的xid出现。
Innodb trx_id
Xid是有server层维护的,innodb内部使用xid为了能够在innodb事务和server之间做联系,但是,innodb的trx_id,是另外维护的,事务id。
Innodb内存维护了一个max_trx_id全局变量,每次需要申请一个新的trx_id时,就获得max_trx_id的当前值,并加1.
Innodb数据可见性的核心思想是:每一行数据都记录了更新它的trx_id,当一个事务读到一行数据的时候,判断这个数据是否可见的方法,就是通过事务的一致性视图与这行数据的trx_id进行对比。
对于正在执行的事务,可以通过information_schema.innodb_trx看到trx_id
(system@127.0.0.1:3306) [test]> select trx_id,trx_mysql_thread_id from information_schema.innodb_trx;

|
SESSION A |
SESSION B |
|
begin; select * from t limit 1; |
|
|
select trx_id,trx_mysql_thread_id from information_schema.innodb_trx; |
|
|
insert into t values('2018-4-2',2); |
|
|
select trx_id,trx_mysql_thread_id from information_schema.innodb_trx; |
Session a开始是一个只读事务,对于只读事务,innodb并不会分配trx_id,trx_id就是0,但是有一个很大的数,只是显示用的,在insert的时候,事务才真正分配了trx_id
只读事务不分配trx_id
--1 可以减小事务视图里面活跃事务数组的大小,因为当前正在运行的只读事务,是不影响数据的可见性判断的,所以,在创建事务的一致性视图时,innodb就只需要拷贝只读事务的trx_id
--2 可以减少trx_id的申请次数,普通的select语句不申请trx_id,大大减少了并发事务申请trx_id的锁冲突。
max_trx_id会持久化存储,重启也不会重置为0,那么从理论上讲,只要一个mysql服务跑得足够久,就可能出现max_trx_id达到2^48-1的上限,然后从0开始的情况。
当达到这个状态后,mysql就会持续出现一个脏读的bug。事务的可见性就根据trx_id来进行比较的。
thread_id
线程id(thread_id),线程id才是mysql中最常见的一种自增id,平时在show processlist里面的第一列,就是thead_id,系统保存了一个全局变量thread_id_counter,每新建一个连接,就讲thread_id_counter赋值给这个新连接的线程变量。
thread_id_counter定义的大小是4个字节,因此达到2^32-1后,就会重置为0,然后继续增加,但是不会在show processlist中看到两个相同的thread_id。
45 MySQL自增id的更多相关文章
- MySQL自增ID 起始值 修改方法
在mysql中很多朋友都认为字段为AUTO_INCREMENT类型自增ID值是无法修改,其实这样理解是错误的,下面介绍mysql自增ID的起始值修改与设置方法. 通常的设置自增字段的方法: 创建表格时 ...
- Mysql自增ID起始值修改
在mysql中很多朋友都认为字段为AUTO_INCREMENT类型自增ID值是无法修改,其实这样理解是错误的,下面介绍mysql自增ID的起始值修改与设置方法.通常的设置自增字段的方法:创建表格时添加 ...
- mysql自增id归0
mysql自增id归0 ALTER TABLE table_name AUTO_INCREMENT=1;
- mysql自增id超大问题查询
引言 小A正在balabala写代码呢,DBA小B突然发来了一条消息,"快看看你的用户特定信息表T,里面的主键,也就是自增id,都到16亿了,这才多久,在这样下去过不了多久主键就要超出范围了 ...
- 基于MySQL自增ID字段增量扫描研究
目录 目录 1 1. 问题 1 2. 背景 1 3. InnoDB表 2 3.1. 自增ID为主键 2 3.2. 自增ID为普通索引 4 3.3. 原因分析 7 4. MyISAM表 8 4.1. 自 ...
- mysql 自增id
在开发的时候遇到了 自增id变成2147483647 莫名其妙 然后发现是自己没把自增id改为 无符号的原因 把无符号勾上就ok了
- mysql自增id获取失败
php 数据库pdo对象,如果是返回,如以下伪代码 function getData(){ return $data; } $data = getData(); $id = $data->las ...
- mysql自增ID
InnoDB引擎的表,执行清空操作之后,表的auto_increment值不会受到影响:一旦重启MySQL,auto_increment值将变成1. MyISAM引擎的表,执行清空操作之后,表的aut ...
- 设置(更改)Mysql 自增ID的起始值
SELECT * FROM segwords WHERE id>790511 DELETE FROM segwords WHERE id>790511 #下面这句是设置的 ALTER TA ...
随机推荐
- 配置ssh免密码登录设置后还是提示需要输入密码
工作之余搭建了一个集群测试,配置了ssh免密码登录以后 ,所有的ssh-copy-id 密钥也都分发了 ,各项配置也没有问题,但是使用ssh进行免密登录时,没有报错,但是要输入被ssh主机的登录密码 ...
- 事件流程以及dom2级事件绑定
事件流程分为三个阶段:捕获阶段.目标阶段.冒泡阶段. 捕获阶段:事件从最顶层元素开始执行,一层层往下,直到精确元素. 目标阶段:事件在精确元素上执行. 冒泡阶段:事件从精确元素开始执行,一层层往上,直 ...
- GUI学习之二十一——QSlider、QScroll、QDial学习总结
上一章我们学习了QAbstractSlider的用法,在讲功能的时候我们是借助了它的子类QSlider来实现的,今天来学习一下它的三个子类——QSlider.QScroll和QDial. 一.QSli ...
- 线段树维护区间前k小
线段树维护区间前k小 $ solution: $ 觉得超级钢琴太麻烦?在这里线段树提供一条龙服务 . 咳咳,开始讲正题!这道题我们有一个和超级钢琴复杂度一样 $ ~O(~\sum x\times lo ...
- ThinkPHP生成静态页buildHtml方法
原来ThinkPHP自带了生成静态页的函数buildHtml,使用起来很方便!最新的手册里没写这个方法,向大家介绍一下. PHP 1 2 3 4 5 6 7 8 9 10 11 protect ...
- Linux下升级安装Python-3.6.9版本
1.操作系统信息 (1)cat /etc/redhat-releas (2)Red Hat Enterprise Linux Server release 6.0 (Santiago) 2.安装开发 ...
- pyqt5-橡皮筋控件QRubberBand
提供一个矩形或线来指示选择或边界 一般结合鼠标事件一同协作 继承于 QWidget import sys from PyQt5.QtWidgets import QApplication, QWidg ...
- Linux发行版和内核版本
1./etc/issue 和 /etc/redhat-release都是系统安装时默认的发行版本信息,通常安装好系统后文件内容不会发生变化. 2.lsb_release -a :FSG(Free St ...
- echart-如何画自定义的图形,三角形为例
- UTC和GMT
UTC GMT UTC = Coordinated Universal Time. 中文名称为协调世界时. GMT = Greenwich Mean Time. 中文名称为格林尼治(平)时 UTC = ...