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 ...
随机推荐
- Bootstrap前端框架快速入门专题
1.Bootstrap简介 Bootstrap,出自自 Twitter,是目前最受欢迎的前端框架. Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的前端框架,它简洁灵活,使得 W ...
- ab压测
安装:yum install -y httpd-tools 验证:ab -V ab -help:-n requests 要执行请求总数,默认会执行一个请求 -c concurrency 一次执行多个请 ...
- Linux系统性能测试工具(六)——磁盘io性能工具之dd
本文介绍关于Linux系统(适用于centos/ubuntu等)的磁盘io性能测试工具-dd.磁盘io性能测试工具包括: fio: dd
- Apache 网站日志分析
1.获得访问前 10 位的 ip 地址 [root@apache ~]# cat access_log |awk '{print $1}'|sort|uniq -c|sort -nr|head -10 ...
- 对于springmvc 很奇妙的报404错误的记录
@RequestMapping("/editItems") public ModelAndView editItems(Integer id) throws Exception { ...
- Cookie、Session和Django分页
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- 管线命令(Pipe)
管线命令接受|前面传来的stdout,管线示意图如下所示: 管线两个需要注意的地方: 1.管线仅会处理stdout,忽略对stderr的处理 2.管线必须接受前个指令的stdin才是 那么,如果我想接 ...
- 【SaltStack官方版】—— states教程, part 4 - states 说明
STATES TUTORIAL, PART 4 本教程建立在第1部分.第2部分.第3部分涵盖的主题上.建议您从此开始.这章教程我们将讨论更多 sls 文件的扩展模板和配置技巧. This part o ...
- Java调用Fortran生成so库报“libifport.so.5: 无法打开共享对象文件”错误解决方法
source /opt/intel/bin/compilervars.sh intel64
- 对postman的研究
1.Postman可用作macOS,Windows和Linux操作系统的本机应用程序. 2.最常用的方法是GET,POST,PUT和DELETE.方法的名称是不言自明的.例如,GET使您可以从服务器检 ...