iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >Mysql中INNODB自增主键的问题有哪些
  • 313
分享到

Mysql中INNODB自增主键的问题有哪些

2024-04-02 19:04:59 313人浏览 泡泡鱼
摘要

小编给大家分享一下Mysql中INNODB自增主键的问题有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!背景: &nbs

小编给大家分享一下Mysql中INNODB自增主键的问题有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

背景:

      自增长是一个很常见的数据属性,在mysql中大家都很愿意让自增长属性的字段当一个主键。特别是InnoDB,因为InnoDB的聚集索引的特性,使用自增长属性的字段当主键性能更好,这里要说明下自增主键需要注意的几个事项。

问题一:表锁

      在Mysql5.1.22之前,InnoDB自增值是通过其本身的自增长计数器来获取值,该实现方式是通过表机制来完成的(AUTO-INC LOCKING)。锁不是在每次事务完成后释放,而是在完成对自增长值插入的SQL语句后释放,要等待其释放才能进行后续操作。比如说当表里有一个auto_increment字段的时候,innoDB会在内存里保存一个计数器用来记录auto_increment的值,当插入一个新行数据时,就会用一个表锁来锁住这个计数器,直到插入结束。如果大量的并发插入,表锁会引起SQL堵塞。insert into.....select大量插入数据的性能也比较差

      在5.1.22之后,InnoDB为了解决自增主键锁表的问题,引入了参数innodb_autoinc_lock_mode,该实现方式是通过轻量级互斥量的增长机制完成的。它是专门用来在使用auto_increment的情况下调整锁策略的,目前有三种选择:

插入类型说明:

INSERT-LIKE:指所有的插入语句,比如 INSERT、REPLACE、INSERT…SELECT、REPLACE…SELECT,LOAD DATA等
Simple inserts:指在插入前就能确定插入行数的语句,包括INSERT、REPLACE,不包含INSERT…ON DUPLICATE KEY UPDATE这类语句。
Bulk inserts:指在插入前不能确定得到插入行的语句。如INSERT…SELECT,REPLACE…SELECT,LOAD DATA.
Mixed-mode inserts:指其中一部分是自增长的,有一部分是确定的。

0:通过表锁的方式进行,也就是所有类型的insert都用AUTO-inc locking。

1:默认值,对于simple insert 自增长值的产生使用互斥量对内存中的计数器进行累加操作,对于bulk insert 则还是使用表锁的方式进行。

2:对所有的insert-like 自增长值的产生使用互斥量机制完成,性能最高,并发插入可能导致自增值不连续,可能会导致Statement 的 Replication 出现不一致,使用该模式,需要用 Row Replication的模式。

      在mysql5.1.22之前,mysql的INSERT-LIKE语句会在执行整个语句的过程中使用一个AUTO-INC锁将表锁住,直到整个语句结束(而不是事务结束)。因此在使用INSERT…SELECT、INSERT…values(…),values(…)时,LOAD DATA等耗费时间较长的操作时,会将整个表锁住,而阻塞其他的insert-like,update等语句。推荐使用程序将这些语句分成多条语句,一一插入,减少单一时间的锁表时间。

解决:

通过参数innodb_autoinc_lock_mode =1/2解决,并用simple inserts 模式插入。

问题二:自增主键不连续

5.1.22后 默认:innodb_autoinc_lock_mode = 
直接通过分析语句,获得要插入的数量,然后一次性分配足够的auto_increment id,只会将整个分配的过程锁住。

root@localhost : test 04:23:28>show variables like 'innodb_autoinc_lock_mode'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 1 | +--------------------------+-------+ 1 row in set (0.00 sec)

root@localhost : test 04:23:31>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.16 sec)

root@localhost : test 04:23:35>insert into tmp_auto_inc(talkid) select talkId from talk_dialog limit 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0 root@localhost : test 04:23:39>show create table tmp_auto_inc\G; *************************** 1. row *************************** Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)

插入10条记录,但表的AUTO_INCREMENT=16,再插入一条的时候,表的自增id已经是不连续了。

原因:

      参数innodb_autoinc_lock_mode = 1时,每次会“预申请”多余的id(handler.cc:compute_next_insert_id),而insert执行完成后,会特别将这些预留的id空出,就是特意将预申请后的当前最大id回写到表中(dict0dict.c:dict_table_autoinc_update_if_greater)。

      这个预留的策略是“不够时多申请几个”, 实际执行中是分步申请。至于申请几个,是由当时“已经插入了几条数据N”决定的。当auto_increment_offset=1时,预申请的个数是 N-1。

      所以会发现:插入只有1行时,你看不到这个现象,并不预申请。而当有N>1行时,则需要。多申请的数目为N-1,因此执行后的自增值为:1+N+(N-1)。测试中为10行,则:1+10+9 =20,和 16不一致?原因是:当插入8行的时候,表的AUTO_INCREMENT已经是16了,所以插入10行时,id已经在第8行时预留了,所以直接使用,自增值仍为16。所以当插入8行的时候,多申请了7个id,即:9,10,11,12,13,14,15。按照例子中的方法插入8~15行,表的AUTO_INCREMENT始终是16
为了发现规律,这儿我做了实验,不是很准确,插入行数与对应的autocommit分别是 2》4   3》4   4-7》8  8-15》16 16-31》32),只能说AUTO_INCREMENT有可能是2n(具体什么时候是2n还没发现规律),范围应该是[n,2n]之间

验证:

插入16行:猜测 预申请的id:1+16+(16-1)= 32,即:AUTO_INCREMENT=32

root@localhost : test 04:55:45>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 04:55:48>insert into tmp_auto_inc(talkid) select talkId from sns_talk_dialog limit 16;
Query OK, 16 rows affected (0.00 sec)
Records: 16 Duplicates: 0 Warnings: 0 root@localhost :
test 04:55:50>show create table tmp_auto_inc\G;
*************************** 1. row ***************************
Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)               ---第一次插入所以为2*16



和猜测的一样,自增id到了32。所以当插入16行的时候,多申请了17,18,19...,31 。

所以导致ID不连续的原因是因为innodb_autoinc_lock_mode = 1时,会多申请id。好处是:一次性分配足够的auto_increment id,只会将整个分配的过程锁住。

5.1.22前 默认:innodb_autoinc_lock_mode = 0

root@localhost : test 04:25:12>show variables like 'innodb_autoinc_lock_mode';
+--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_autoinc_lock_mode | 0 | +--------------------------+-------+
1 row in set (0.00 sec)

root@localhost : test 04:25:15>create table tmp_auto_inc(id int auto_increment primary key,talkid int)engine = innodb default charset gbk;
Query OK, 0 rows affected (0.17 sec)

root@localhost : test 04:25:17>insert into tmp_auto_inc(talkid) select talkId from talk_dialog limit 10;
Query OK, 10 rows affected (0.00 sec)
Records: 10 Duplicates: 0 Warnings: 0
root@localhost : test 04:25:21>show create table tmp_auto_inc\G;
*************************** 1. row ***************************
Table: tmp_auto_inc Create Table: CREATE TABLE `tmp_auto_inc` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `talkid` int(11) DEFAULT NULL, PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=gbk 1 row in set (0.00 sec)

插入10条记录,但表的AUTO_INCREMENT=11,再插入一条的时候,表的自增id还是连续的。

innodb_autoinc_lock_mode = 2 和 innodb_autoinc_lock_mode = 1 的测试情况一样。但该模式下是来一个分配一个,而不会锁表,只会锁住分配id的过程,和1的区别在于,不会预分配多个,这种方式并发性最高。但是在replication中当binlog_fORMat为statement-based时存在问题

解决:

尽量让主键ID没有业务意义,或则使用simple inserts模式插入。

结论:

当innodb_autoinc_lock_mode为0时候, 自增id都会连续,但是会出现表锁的情况,解决该问题可以把innodb_autoinc_lock_mode 设置为1,甚至是2。会提高性能,但是会在一定的条件下导致自增id不连续。

以上是“Mysql中INNODB自增主键的问题有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: Mysql中INNODB自增主键的问题有哪些

本文链接: https://www.lsjlt.com/news/62750.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Mysql中INNODB自增主键的问题有哪些
    小编给大家分享一下Mysql中INNODB自增主键的问题有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!背景: &nbs...
    99+
    2022-10-18
  • 解决mysql的int型主键自增问题
    引入 我们在使用mysql数据库时,习惯使用int型作为主键,并设置为自增,这既能够保证唯一,使用起来又很方便,但int型的长度是有限的,如果超过长度怎么办呢? 暴露问题 我们先创建...
    99+
    2022-11-12
  • 数据库自增主键可能产生的问题有哪些
    数据库自增主键可能产生的问题包括:1. 插入数据时可能存在并发问题。如果多个线程同时插入数据,可能会导致主键冲突,从而导致插入失败。...
    99+
    2023-09-27
    数据库
  • Mysql更新自增主键id遇到的问题
    目录为什么要更新自增id问题如何解决本是一个自己知道的问题,还是差点踩坑(差点忘了,还好上线前整理上线点时想起来了),特此记录下来 为什么要更新自增id 我是因为历史业务上的坑,导致...
    99+
    2022-11-12
  • mysql为什么InnoDB表最好要有自增列做主键
    本篇内容介绍了“mysql为什么InnoDB表最好要有自增列做主键”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有...
    99+
    2022-10-18
  • 如何解决mysql的int型主键自增问题
    这篇文章主要介绍“如何解决mysql的int型主键自增问题”,在日常操作中,相信很多人在如何解决mysql的int型主键自增问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何解决mysql的int型主键自...
    99+
    2023-06-20
  • 如何解决Mysql更新自增主键id遇到的问题
    这篇文章主要为大家展示了“如何解决Mysql更新自增主键id遇到的问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何解决Mysql更新自增主键id遇到的问题”这篇文章吧。为什么要更新自增id...
    99+
    2023-06-21
  • Oracle实现主键字段自增的方式有哪些
    今天小编给大家分享一下Oracle实现主键字段自增的方式有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们...
    99+
    2023-03-15
    oracle
  • pt-archiver和自增主键的问题怎么解决
    今天小编给大家分享一下pt-archiver和自增主键的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。前言pt-...
    99+
    2023-06-30
  • MySQL中的主键自增机制详情
    目录主键自增自增主键保存在哪里自增值修改机制自增值的修改时机如何修改自增主键值主键自增 mysql 提供了主键自增机制 AUTO_INCREMENT. 对主键使用, 保证了主键的唯一性. 注意:自增长必须与主键字段配合使...
    99+
    2022-08-26
  • 删除mysql中自增主键的方法
    小编给大家分享一下删除mysql中自增主键的方法,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!删除mysql中的自增主键的方法:首先需要删除auto_increment;然后执行【alter ...
    99+
    2022-10-18
  • MySQL中自增主键的示例分析
    这篇文章主要介绍了MySQL中自增主键的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、自增值保存在哪儿?不同的引擎对于自增值的保...
    99+
    2022-10-18
  • MySQL中的自增主键怎么修改
    这篇文章主要介绍“MySQL中的自增主键怎么修改”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“MySQL中的自增主键怎么修改”文章能帮助大家解决问题。一、自增值保存...
    99+
    2022-10-19
  • MySQL数据库删除数据后自增主键不连续的问题
    在日常使用MySQL时,我们手动删除几条记录后,会发现后续的数据主键自增出现不连续的情况 我们可以执行如下代码解决 如果删除完数据还没有新增数据,即还没有出现不连贯的数据ID时,执行以下语句: ALTER TABLE 表名 AUTO_INC...
    99+
    2023-09-05
    数据库 mysql sql
  • 数据库主键相关问题有哪些
    这篇文章主要讲解了“数据库主键相关问题有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“数据库主键相关问题有哪些”吧!1 是否每张表都应该有自增主键?不一定自增主键可以加快行的插入速度,对...
    99+
    2023-06-27
  • mysql中外键和主键的区别有哪些
    这篇文章主要介绍“mysql中外键和主键的区别有哪些”,在日常操作中,相信很多人在mysql中外键和主键的区别有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”mysql中...
    99+
    2022-10-19
  • MyBatis处理mysql主键自动增长出现的不连续问题解决
    问题产生 设置了mysql主键自动增长,但因为删除字段的操作导致主键不连续 解决方法 step1:在mapper.xml文件中添加update标签设置自动增长的增量为1 alte...
    99+
    2022-11-12
  • 详解mybatis插入数据后返回自增主键ID的问题
    1.场景介绍: ​开发过程中我们经常性的会用到许多的中间表,用于数据之间的对应和关联.这个时候我们关联最多的就是ID,我们在一张表中插入数据后级联增加到关联表中.我们熟知...
    99+
    2022-11-12
  • MySQL数据库的主从配置有哪些问题
    这篇文章主要介绍MySQL数据库的主从配置有哪些问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!  MySQL数据库是一种功能性不是很强大的关系型数据库管理系统,尽管功能不完善,但...
    99+
    2022-10-19
  • 浅谈MySQL中的自增主键用完了怎么办
    在面试中,大家应该经历过如下场景 面试官:"用过mysql吧,你们是用自增主键还是UUID?"    你:"用的是自增主键"     面试官:"为什么是自增主键?" &nbs...
    99+
    2022-05-21
    MySQL 自增主键用完 MySQL 自增主键
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作