##=====================================================================================##

在数据库表设计中会纠结于”自然键”和”代理键”的选择,自然键在实现数据“软删除”时实现比较复杂,部分自然键因为键值过长或多列组合导致不适合作为表主键,而比较常见两种代理键为自增列(auto incremnet)和全局唯一标识列(GUID)。

使用自增列作为主键的优缺点:

1、    主键键值长度短,INT列需要4个字节,BIGINT列需要8个字节;

2、    自增主键顺序递增,在INSERT操作时”顺序”写入表;

3、    由于数据集中插入到表尾部,在高并发情况下容易造成”数据页热点”,影响插入效率;

4、    自增主键只能保证在表内数据唯一,对于分库分表场景,可能因错误操作产生相同的“唯一值”。

使用GUID列的优缺点:

1、    32位GUID字符串需要更多的存储空间来存放(具体存储长度与字符集相关),影响主键和其他索引的查询性能。

2、    GUID可实现全局唯一,能保证在多个表之间的数据唯一性

3、    GUID将数据分散到全表,不会产生热点数据页,但会造成大量随机IO读写

在实际使用过程中,很少场景会使用GUID作为主键,大部分业务按照数据量需求使用INT或BIGINT的自增列作为主键,对于需要多表唯一的场景可以通过程序实现全局唯一的自增ID。

##=====================================================================================##

MySQL在很早版本便支持自增列并在各版本中优化自增列功能,在MySQL 5.1.22版本引入轻量级互斥自增长实现机制,MySQL 5.5版本中引入change buffer特性,在MySQL 8.0版本引入自增列持久化。针对目前京东主要使用MySQL 5.5/5.6/5.7三个主版本,罗列部分使用自增列需要掌握的知识点:

知识点1:自增列数据类型选择问题

自增列除常见的TINYINT/SMALLINT/INT/BIGINT等整数数据类型外,还可以使用FLOAT等浮点数数据类型,但强烈建议不使用非整数数据类型作为自增列。

选取数据类型时:

1、    按照所需要范围值进行最小化选取,如果只需要0-20的范围值,则选择可以存放-128到127数值的TINYINT。

2、    当所需自增范围值不确定时,建议选择足够使用的数据类型,先保证数据安全再考虑操作性能,相同数据量下,使用BIGINT并不会比使用INT带来太多性能影响。京东订单号在前期设计时使用INT数据类型,当INT无法满足需求时,商城花费大量资源进行INT到BIGINT的升级改造,同时影响诸多关联系统。

##=====================================================================================##

知识点2:自增列跳号问题

1、无论MySQL还是其他关系型数据库,为提高自增列的生成效率,都将生成自增值的操作设计为非事务性操作,表现为当事务回滚时,事务中生成的自增值不会被回滚。

2、当对自增表进行批量插入时(INSERT … SELECT …),即使在单一会话下,MySQL仍不能保证两次获取到的自增ID值连续,批量插入数据量越大,产生的自增ID跳号范围越大。

自增跳号对普通业务没有太多影响,但对于像发票这类要求号码连续的业务,不能通过自增列来实现。

##=====================================================================================##

知识点3:自增列持久化问题

在MySQL 5.5/5.6/5.7三个版本中,MySQL并不会将自增列分配的自增值信息固化到磁盘,当MySQL重启后,会根据自增列上当前最大值和参数auto_increment_offset来确定下一次的自增值,为快速获取自增列上最大值,MySQL要求自增列必须建有索引。如果一张自增表的数据在重启实例前被清空,实例重启后该表数据会从”1”开始自增(假设表的自增初始值定义为1)。

在一次亚一数据库升级过程中,某张业务表”恰好”因为业务逻辑将表中所有数据删除,重启后该表自增值从1开始生成,当该表数据流转到其他表出现数据冲突,发现问题后,我们紧急手动设置该表自增值,避免事故进一步恶化,并再后期类似操作时,重点关注此类自增表。

建议1:如果业务会对自增表数据进行硬删除,在服务器重启前应重点关注该自增表使用的自增值,可以通过information_schema.tables中的auto_increment列来获取。

PS1:在MySQL 8.0中引入自增列持久化特性,可以避免上述问题。

##=====================================================================================##

知识点4:自增列初始值问题

在运维过程中,会遇到研发同事问为什么新创建的表不是从1开始自增,该问题可以从以下两个角度排查:

1、    建表语句,在使用SHOW CREATE TABLE或MySQLDump等命令导出表结构时,会包含该表当前使用的自增值,如:

2、    全局参数auto_increment_increment和auto_increment_offset,这两全局参数可以作用实例下所有自增表,主要应用在分库分表的场景。

##=====================================================================================##

知识点5:修改数据列为自增数据列

当数据类型为数值类型且表中数据唯一时,可以将该数据列转换为自增列,修改操作会保持列中现有数据,不会重新生成新数据。

##=====================================================================================##

知识点6:修改普通表为自增表

在MySQL中允许使用ALTER TABLE方式为普通表新增一个自增列,但由于ALTER操作为DDL语句,在主从复制时会将该DDL语句传递给从库执行,MySQL并不能保证相同记录在主从服务器上获得相同的自增ID,会导致主从数据差异。

模拟测试:

主库上创建表:CREATE TABLETB1001

(

C1INT);

会话1开启事务并执行:

STARTTRANSACTION;INSERT INTO TB1001(C1) SELECT 1;

会话2执行:INSERT INTO TB1001(C1) SELECT 2;

会话1提交事务。

然后将表修改为自增表:ALTER TABLE TB1001 ADD ID INT PRIMARY KEY AUTO_INCREMENT;

主库数据为:

从库数据为:

原因分析:

在主库上,C1=2的数据晚于C1=1的数据被插入,但由于C1=2的数据所在事务被先提交,因此C1=2的记录先于C1=1的记录在从库上执行,因此两条记录在主库和从库上的插入顺序不同,在生成自增ID时获得到自增ID不同,最终导致数据差异。

建议:在将普通表修改为自增表时,如果表中存在数据,请勿使用ALTER TABLE的方式修改,建议新建自增临时表,然后将数据导入到该表中,再兑换表名。

##=====================================================================================##

mysql 自增列 类型_MySQL--自增列学习相关推荐

  1. mysql 主键自增的范围_MySQL自增主键知识点总结

    自增主键 自增值的存储 MyISAM引擎将当前自增值存储在表数据文件中. InnoDB引擎在5.7及之前将当前自增值存储在内存中,MySQL重启时从表中查询自增列最大值+步长作为当前自增值. Inno ...

  2. mysql取得列类型_Mysql列类型

    数值型 整型: tinyint:微小的列类型,1个字节,默认有符号,存储范围:-128--127 可选属性:tingyint(M) unsigned zerofill M:宽度(在0填充(zerofi ...

  3. mysql 常用的列类型_MySQL 常用列类型

    日期和时间类型为DATETIME.DATE.TIMESTAMP.TIME和YEAR. 注意:在MySQL中,日期时间值使用单引号引起来. 相当于Java中Date,Calender. 最常用的整数类型 ...

  4. mysql 设置日期时间格式_MySQL:更改列类型和日期时间格式

    我的数据库当前将"日期"列设置为varchar(20),我的日期格式如下: 1/13/2015 20:00 我想在数据库上运行更新以将列类型更改为datetime并将当前日期的格式 ...

  5. mysql几种索引类型_Mysql几种索引类型的区别及适用情况

    如大家所知道的,Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE. 那么,这几种索引有什么功能和性能上的不同呢? FULLTEXT 即为全文索引,目前只有MyI ...

  6. mysql 创建临时表 时间类型_MySQL问答系列之什么情况下会用到临时表

    临时表介绍 什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间.为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创 ...

  7. mysql数据库邮箱什么类型_MySQL的数据类型介绍

    MySQL的数据类型介绍 发布时间:2020-06-01 20:57:09 来源:亿速云 阅读:154 作者:鸽子 由于Mysql独有的特性和实现细节对性能的影响是很明显的,因为做好Mysql数据库的 ...

  8. mysql修改表名,列名,列类型,添加表列,删除表列

    alter table test rename test1; --修改表名alter table test add column name varchar(10); --添加表列alter table ...

  9. mysql 人名用什么类型_MySQL 基础(二)

    封面图片来源:沙沙野 01. DDL 数据定义语言 1). 创建表的基本语法 CREATE TABLE 表名( 字段名1 数据类型 约束规则, 字段名2 数据类型, 字段名3 数据类型, ..... ...

  10. mysql多列索引_MySQL的多列索引

    什么是索引? 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面 ...

最新文章

  1. react 项目实战(六)提取布局组件
  2. struts1生成验证码
  3. FSMO角色的Windows界面查看和转移示例
  4. Java7 java.util.concurrent 并发包计划
  5. “2016智能终端峰会新闻发布会暨移动信息化可信选型认证结果发布会” —— 在京成功召开...
  6. Play on Words UVA - 10129 (欧拉回路)
  7. Entity Framework技巧系列之七 - Tip 26 – 28
  8. 【从C到C++学习笔记】引用/const引用/引用传递/引用作为函数返回值/引用和指针的区别
  9. 像京东等大厂为什么不通过减薪来代替裁员,降低成本?
  10. 华硕BIOS TPM设置
  11. 一款网易云音乐歌词制作软件
  12. 谷歌的AI布局:机器学习是重心 继续在中国招人
  13. k8s中的Secret
  14. K9F1G08U0D Nand芯片
  15. python读取xlsx文件pandas_pandas dataframe 读取 xlsx 文件
  16. Android连上USb不充电,手机连接电脑只显示充电没有usb连接怎么办?
  17. USB中文网之虚拟鼠标功能演示
  18. Surface RT应用技巧1
  19. IDEA安装阿里巴巴编码规范插件的两种方式详解(在线安装和离线安装)
  20. el-tree中实现拖拽遇到的问题

热门文章

  1. C++11中range-based for loops中与的区别
  2. SignalTap II逻辑分析仪的使用
  3. Vagrant挂载目录失败mount: unknown filesystem type ‘vboxsf’
  4. Java程序安装失败
  5. 在天气预报中应用机器学习
  6. linux常用命令--diff
  7. 配置PIX515E DMZ的基本方法与故障排除
  8. js 页面history.back()返回上一页,ios 不重新加载ready的解决办法
  9. 关于Oracle AUTONOMOUS TRANSACTION(自治事务)的介绍
  10. 配置ADO.NET类文件连接优化