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 ...
随机推荐
- MFC学习笔记2---简单计算器
前言 学习了鸡啄米网页的前三部分后,我们就可以做一个小软件出来了,我选择先做一个计算器. 这是Win7系统自带的计算器: 为了提升成就感,我将计算器的大部分内容去除,于是就变成这样: 这样就只剩下了1 ...
- 一、left
一.left - right 就是遍历(以左边遍历,以右边遍历) inner join 就是求公共部分的结果集 left join 查询结果 right join结果 inner join 解决的办法 ...
- python基础操作---string
#coding:utf-8 var1 = 'Hello World!' print var1[::] print len(var1) print var1[0:len(var1)] print var ...
- Python自动化学习--鼠标和键盘事件
from selenium import webdriver from selenium.webdriver import ActionChains import time driver = webd ...
- AlphaStar: Mastering the Real-Time Strategy Game StarCraft II 博客要点
original blog: https://deepmind.com/blog/alphastar-mastering-real-time-strategy-game-starcraft-ii S ...
- APIO2019 题解
APIO2019 题解 T1 奇怪装置 题目传送门 https://loj.ac/problem/3144 题解 很容易发现,这个东西一定会形成一个环.我们只需要求出环的长度就解决了一切问题. 设环的 ...
- spring security基本知识(二) 自定义认证
配置自定义的用户存储 我们在 SecurityConfig 的配置类中 重写了 configure(AuthenticationManagerBuilder auth) 方法,我们可以通过 Authe ...
- Django【第25篇】:后端CORS解决跨域问题
解决跨域问题 一.为什么会有跨域问题? 是因为浏览器的同源策略是对ajax请求进行阻拦了,但是不是所有的请求都给做跨域,像是一般的href属性,a标签什么的都不拦截. 二.解决跨域问题的两种方式 JS ...
- re模块下的的常用方法
引入模块: import re 1.查找findall 匹配所有,每一项都是列表中的一个元素 ret=re.findall("\d+","sjkhk172按实际花费9 ...
- java:在Conllection接口中实际上也规定了两个可以将集合变成对象数组的操作
在Conllection接口中实际上也规定了两个可以将集合变成对象数组的操作 //在Conllection接口中实际上也规定了两个可以将集合变成对象数组的操作 List<String> a ...