mysql 主键自增语句_MySQL 自增主键[通俗易懂]

mysql 主键自增语句_MySQL 自增主键[通俗易懂]以下仅考虑InnoDB存储引擎。自增主键有两个性质需要考虑:单调性每次插入一条数据,其ID都是比上一条插入的数据的ID大,就算上一条数据被删除。连续性插入成功时,其数据的ID和前一次插入成功时数据的ID相邻。自增主键的单调性为何会有单调性的问题?这主要跟自增主键最大值的获取方式,以及存放位置有关系。如果最大值是通过计算获取的,并且在某些情况下需要重新获取时,会因为最新的数据被删…

大家好,又见面了,我是你们的朋友全栈君。

以下仅考虑 InnoDB 存储引擎。

自增主键有两个性质需要考虑:

单调性

每次插入一条数据,其 ID 都是比上一条插入的数据的 ID 大,就算上一条数据被删除。

连续性

插入成功时,其数据的 ID 和前一次插入成功时数据的 ID 相邻。

自增主键的单调性

为何会有单调性的问题?

这主要跟自增主键最大值的获取方式,以及存放位置有关系。

如果最大值是通过计算获取的,并且在某些情况下需要重新获取时,会因为最新的数据被删除而减小。

自增主键最大值怎么取的?存放到哪里?

MySQL 5.7 及之前的版本,自增主键最大值会在启动(重启)后从数据库中取出放到内存:

SELECT MAX(ai_col) FROM table_name FOR UPDATE;

这样获取是通过计算的,并且由于存放在内存而容易丢失。

如果删除最新一条数据(假设 ID 为 10),因故障或者其他必要重启后再插入一条数据时会使用之前的 ID (即 ID 为 10)。

问题在于如果有其他表依赖了该 ID,则其他表的数据关联到的数据就符合要求了。除非设置了外键。

比如我要向最大一个 ID 的账号充了 100 万。但是在充值之前,该账号被删除,然后服务器故障重启,重启后有人新注册了一个账号。结果我的 100 万充到了他的新账号上。注册新账号的人以为是新手福利,笑嘻嘻。

如何解决单调性的问题?

从 MySQL 8.0 开始,自增主键最大值会在每次修改后写入到 redo log,并且在每个检查点写入引擎私有的系统表。

如果是正常重启,则读取系统表里的值。

如果是故障重启,则先读取系统表里的值放到内存。接着扫描 redo log 里存储的值。如果扫描到的值大于内存的值,则将该值覆盖到内存。

但由于数据库可能在 redo log 刷入磁盘前就故障了,所以可能会用到之前申请的 ID。

注:如果 redo log 都没刷入,就更不用说将数据插入数据表了。

自增主键插入时的连续性

这里不考虑由于删除导致的连续性问题

为何会有连续性问题?

这主要是跟插入事务回滚有关系。

对于两个插入事务,事务 A 先执行插入语句,之后事务 B 执行插入语句。在这之后,事务 A 回滚,导致 A 执行插入语句时占用的 ID 被抛弃。

之所以事务 A 没提交的情况下,事务 B 就能执行插入语句,跟 InnoDB 的自增长锁(AUTO-INC Locking)相关。该锁是一种特殊的表锁(table-level lock),但会在插入语句执行后立即释放,不会等到事务结束。

如何解决连续性问题?

使用最高隔离级别 SERIALIZABLE (串行)。

由于性能上的考虑,通常不这样做。

多事务批量插入的连续性

事务 A 和事务 B 都在执行 不确定数量 的批量插入(INSERT … SELECT):

保证事务 A 的数据的 ID 连续: innodb_autoinc_lock_mode = 0 (AUTO-INC Locking)

必须等待语句执行结束才释放锁。

保证事务 A 的数据的 ID 连续: innodb_autoinc_lock_mode = 1 (AUTO-INC Locking)

和上面的区别在于,当执行 确定数量 的批量插入时,使用轻量级互斥量(mutex)而不是特殊表锁(AUTO-INC Locking),从而提前向内存的计数器申请相应数量的 ID。之后立即释放,不用等语句执行结束。

会因为回滚而使得全局 ID 不连续。

不保证事务 A 的数据的 ID 连续: innodb_autoinc_lock_mode = 2 (mutex)

三种插入定义:

简单插入

能够提前知道插入的行数

批量插入

不能提前知道插入的行数

混合插入

批量插入中的一部分的 ID 是指定的(非 0 且非 NULL),另一部分未指定,使用数据库生成的自增 ID。

其他

如果主动指定 ID 为 0 或者 NULL 插入,则会使用数据库生成的自增 ID。

参考文档

为什么 MySQL 的自增主键不单调也不连续

https://database.51cto.com/art/202004/614923.htm

《MySQL技术内幕——InnoDB存储引擎》 第 6 章:锁

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/147511.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Linux下文件搜索、查找、查看命令

    Linux下文件搜索、查找、查看命令Linux下文件搜索、查找、查看命令1、最强大的搜索命令:find一、根据文件或目录名称搜索二、根据文件大小搜索三、根据所有者和所属组搜索四、根据时间属性搜索五、根据文件类型或i节点搜索六、组合条件搜索  2、在文件资料中查找文件:locate  3、搜索命令所在的目录及别名信息:which 4、搜索命令所在的目录及帮助文档路径:whereis5、在文件…

    2022年7月26日
    11
  • 下拉列表框DropDownList绑定Dictionary泛型类

    下拉列表框DropDownList绑定Dictionary泛型类DropDownList绑定Dictionary泛型类定义一个Dictionary泛型类///<summary>   ///产品类型   ///</summary>   ///<returns></returns>   publicDictionary<string,string>productType() …

    2022年10月8日
    4
  • 能用python开发手机软件吗_python numpy

    能用python开发手机软件吗_python numpy有许多人对如何在手机上进行python开发感到很困惑,今天我就给大家推荐几个比较好的python开发软件。一.QPythonOHQPython真的是一款好的软件,它可以支持Python库的安装。内置sl4aserver,简直是一款神器!二.Pydroid3Pydroid3是我目前见过的最好的一款python编辑器,他可以使用pip,甚至可以在手机上掉。…

    2022年8月12日
    6
  • 玩玩三维重建–Visual SFM介绍

    玩玩三维重建–Visual SFM介绍转自:  奇点视觉        原文地址玩玩三维重建Leaveareply版权声明:本文系本站作者自己翻译整理,欢迎转载,但转载请以超链接形式注明文章来源(planckscale.info)、作者信息和本声明,否则将追究法律责任。我们在实时三维重建方面的工作今年已经密集展开。或许不久后某一天,你会在本站看到带有SLA

    2022年6月20日
    104
  • php 取历史值,从新浪获取股票历史数据[通俗易懂]

    php 取历史值,从新浪获取股票历史数据[通俗易懂]转自:http://blog.163.com/fluxray_sensor/blog/static/2965101520085213574929/这几天在网上找股票的历史数据想研究研究,最后找到一个不错的接口,来自于雅虎,是在一个博客上找到的,地址为:http://www.bizeway.net/read.php?317。不过这个不是我第一个找到的接口,最初始我是想直接解析新浪的历史交易页面,不…

    2022年6月24日
    22
  • nginx负载均衡的原理简介_负载均衡原理

    nginx负载均衡的原理简介_负载均衡原理1、Nginx负载均衡的原理是什么?​客户端向反向代理发送请求,接着反向代理根据某种负载机制转发请求至目标服务器(这些服务器都运行着相同的应用),并把获得的内容返回给客户端,期中,代理请求可能根据配置被发往不同的服务器。2、Nginx负载均衡的作用是什么?​负载均衡:分摊到多个操作单元上进行执行,和它的英文名称很匹配。就是我们需要一个调度者,保证所有后端服务器都将性能充分发挥,从而保持服…

    2022年10月9日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号