精华内容
下载资源
问答
  • MySQL自增主键详解

    万次阅读 多人点赞 2019-06-02 10:02:16
    出现了自增主键不连续的情况 唯一键冲突和事务回滚都会导致自增主键id不连续的情况 四、自增锁的优化 自增id锁并不是一个事务锁,而是每次申请完就马上释放,以便允许别的事务再申请 但在MySQL5.0版本的时候,自增锁...

    一、自增值保存在哪儿?

    不同的引擎对于自增值的保存策略不同

    1.MyISAM引擎的自增值保存在数据文件中

    2.InnoDB引擎的自增值,在MySQL5.7及之前的版本,自增值保存在内存里,并没有持久化。每次重启后,第一次打开表的时候,都会去找自增值的最大值max(id),然后将max(id)+步长作为这个表当前的自增值

    select max(ai_col) from table_name for update;
    

    在MySQL8.0版本,将自增值的变更记录在了redo log中,重启的时候依靠redo log恢复重启之前的值

    二、自增值修改机制

    如果字段id被定义为AUTO_INCREMENT,在插入一行数据的时候,自增值的行为如下:

    1.如果插入数据时id字段指定为0、null或未指定值,那么就把这个表当前的AUTO_INCREMENT值填到自增字段

    2.如果插入数据时id字段指定了具体的值,就直接使用语句里指定的值

    假设,某次要插入的值是X,当前的自增值是Y

    1.如果X<Y,那么这个表的自增值不变

    2.如果X>=Y,就需要把当前自增值修改为新的自增值

    新的自增值生成算法是:从auto_increment_offset(初始值)开始,以auto_increment_increment(步长)为步长,持续叠加,直到找到第一个大于X的值,作为新的自增值

    三、自增值的修改时机

    创建一个表t,其中id是自增主键字段、c是唯一索引,建表语句如下:

    CREATE TABLE `t` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `c` int(11) DEFAULT NULL,
      `d` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `c` (`c`)
    ) ENGINE=InnoDB;
    

    假设,表t里面已经有了(1,1,1)这条记录,这时再执行一条插入数据命令:

    insert into t values(null, 1, 1); 
    

    执行流程如下:

    1.执行器调用InnoDB引擎接口写入一行,传入的这一行的值是(0,1,1)

    2.InnoDB发现用于没有指定自增id的值,获取表t当前的自增值2

    3.将传入的行的值改成(2,1,1)

    4.将表的自增值改成3

    5.继续执行插入数据操作,由于已经存在c=1的记录,所以报Duplicate key error(唯一键冲突),语句返回

    对应的执行流程图如下:
    在这里插入图片描述
    在这之后,再插入新的数据行时,拿到的自增id就是3。出现了自增主键不连续的情况

    唯一键冲突和事务回滚都会导致自增主键id不连续的情况

    四、自增锁的优化

    自增id锁并不是一个事务锁,而是每次申请完就马上释放,以便允许别的事务再申请

    但在MySQL5.0版本的时候,自增锁的范围是语句级别。也就是说,如果一个语句申请了一个表自增锁,这个锁会等语句执行结束以后才释放

    MySQL5.1.22版本引入了一个新策略,新增参数innodb_autoinc_lock_mode,默认值是1

    1.这个参数设置为0,表示采用之前MySQL5.0版本的策略,即语句执行结束后才释放锁

    2.这个参数设置为1

    • 普通insert语句,自增锁在申请之后就马上释放
    • 类似insert … select这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放

    3.这个参数设置为2,所有的申请自增主键的动作都是申请后就释放锁

    为了数据的一致性,默认设置为1
    在这里插入图片描述
    如果sessionB申请了自增值以后马上就释放自增锁,那么就可能出现这样的情况:

    • sessionB先插入了两行数据(1,1,1)、(2,2,2)
    • sessionA来申请自增id得到id=3,插入了(3,5,5)
    • 之后,sessionB继续执行,插入两条记录(4,3,3)、(5,4,4)

    当binlog_format=statement的时候,两个session是同时执行插入数据命令的,所以binlog里面对表t2的更新日志只有两种情况:要么先记sessionA的,要么先记录sessionB的。无论是哪一种,这个binlog拿到从库执行,或者用来恢复临时实例,备库和临时实例里面,sessionB这个语句执行出来,生成的结果里面,id都是连续的。这时,这个库就发生了数据不一致

    解决这个问题的思路:

    1)让原库的批量插入数据语句,固定生成连续的id值。所以,自增锁直到语句执行结束才释放,就是为了达到这个目的

    2)在binlog里面把插入数据的操作都如实记录进来,到备库执行的时候,不再依赖于自增主键去生成。也就是把innodb_autoinc_lock_mode设置为2,同时binlog_format设置为row

    如果有批量插入数据(insert … select、replace … select和load data)的场景时,从并发插入数据性能的角度考虑,建议把innodb_autoinc_lock_mode设置为2,同时binlog_format设置为row,这样做既能并发性,又不会出现数据一致性的问题

    对于批量插入数据的语句,MySQL有一个批量申请自增id的策略:

    1.语句执行过程中,第一次申请自增id,会分配1个

    2.1个用完以后,这个语句第二次申请自增id,会分配2个

    3.2个用完以后,还是这个语句,第三次申请自增id,会分配4个

    4.依次类推,同一个语句去申请自增id,每次申请到的自增id个数都是上一次的两倍

    insert into t values(null, 1,1);
    insert into t values(null, 2,2);
    insert into t values(null, 3,3);
    insert into t values(null, 4,4);
    create table t2 like t;
    insert into t2(c,d) select c,d from t;
    insert into t2 values(null, 5,5);
    

    insert … select,实际上往表t2中插入了4行数据。但是,这四行数据是分三次申请的自增id,第一次申请到了id=1,第二次被分配了id=2和id=3,第三次被分配到id=4到id=7

    由于这条语句实际上只用上了4个id,所以id=5到id=7就被浪费掉了。之后,再执行insert into t2 values(null, 5,5),实际上插入了的数据就是(8,5,5)

    这是主键id出现自增id不连续的第三种原因

    五、自增主键用完了

    自增主键字段在达到定义类型上限后,再插入一行记录,则会报主键冲突的错误

    以无符号整型(4个字节,上限就是23212^{32}-1)为例,通过下面这个语句序列验证一下:

    CREATE TABLE t ( id INT UNSIGNED auto_increment PRIMARY KEY ) auto_increment = 4294967295;
    INSERT INTO t VALUES(NULL);
    INSERT INTO t VALUES(NULL);
    

    第一个insert语句插入数据成功后,这个表的AUTO_INCREMENT没有改变(还是4294967295),就导致了第二个insert语句又拿到相同的自增id值,再试图执行插入语句,报主键冲突错误

    推荐资料

    https://time.geekbang.org/column/article/80531

    展开全文
  • 自增主键

    万次阅读 2020-09-15 23:09:42
    在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的...

          在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降.

     

        总之,在数据量大一些的情况下,用自增主键性能会好一些

    展开全文
  • C++前自增自增

    2020-05-18 10:22:17
    C++前自增自增 #include <iostream> #include <cstring> using namespace std; int main() { /**前自增**/ int nLen = 10; int nCount = ++nLen; cout << "nLen=" << nLen <...

    C++前自增后自增

    
    #include <iostream>
    #include <cstring> 
    
    
    using namespace std;
    
    int main() 
    {
        /**前自增**/
        int nLen = 10;
        int nCount = ++nLen;
        cout << "nLen=" << nLen << endl;
        cout << "nCont=" << nCount << endl;
        /**后自增**/
        int nLen1 = 10;
        int nCount1 = nLen++;
        cout << "nLen=" << nLen1 << endl;
        cout << "nCont=" << nCount1 << endl;
    }
    
    
    展开全文
  • mysql自增和orcale自增

    2018-06-14 13:49:42
    一、自增二、自增的写法三、自增的id获取 1)mysql获取自增的下一个id值SELECT Auto_increment FROM information_schema.`TABLES` WHERE Table_Schema='数据库名称' AND table_name = '表明' limit 1; 2)orcale...

    一、自增

    二、自增的写法

    三、自增的id获取

            1)mysql获取自增的下一个id值

    SELECT Auto_increment FROM information_schema.`TABLES` WHERE Table_Schema='数据库名称' AND table_name = '表明' limit 1;

            2)orcale自增

    展开全文
  • Java的自增 (分为先自增与后自增

    千次阅读 2019-06-04 16:29:33
    Java的自增 (分为先自增与后自增)。 举例: 1.后自增 int a=3; int b=a++; //先把a赋值给b,然后a再自增一次 //下面输出a和b System.out.println("a="+a); System.out.println("b="+b); 输出结果为:a=4,b=3...
  • 自增和后自增

    2017-09-20 20:02:05
    本文主要讲解前自增和后自增的使用以及细节,另外前自减和后自减没在文章中详细介绍,但原理同前自增和后自增
  • 自增约束

    2020-01-12 19:10:36
    自增约束 1、关键字:auto_increment 2、特点: (1)一个表只能有一个自增列 (2)自增列必须是整型的 (3)自增列必须是键列,例如:主键,唯一键 3、如何指定自增 create table emp( eid int primary key auto_...
  • DESC:达梦判断哪列是自增列|查询自增信息|重构自增列|自增改为sequence Last Update:2020-7-1 10:58 判断自增列 left JOIN (SELECT * FROM syscolumns t WHERE id = (SELECT object_id FROM dba_objects t WHERE 1...
  • oracle自增序列

    2016-05-24 05:51:10
    自增序列
  • 单号自增

    2019-07-28 20:04:39
    单号自增 开发工具与关键技术:Visual Studio 2015 作者:昨夜星辰 撰写时间:2019年 07月28 日 一、单号自增,单号自增是通过单号的数值,在通过数据库查询到单号的数值,然后获取数据自增,因为是单号自增所以每...
  • 有的表需要添加自增列,在添加新纪录时自动添加一个序号,有两种不错的方法通过T-SQL代码、通过企业管理器在此分享给大家
  • Oracle自增

    2019-04-11 14:41:45
    MySQL可以主键自增,可以直接勾选主键自增,而Oracle不可以,需要写一条语句,再对id进行主键自增赋值: 主键自增的Oracle语句:SELECT AUTOID.NextVal FROM DUAL 写一个mapper单独存放主键自增:<mapper ...
  • 文章目录自增变量自增变量介绍(1)自增变量是什么?(2)有什么特点自增变量案例1自增变量案例2自增变量案例3javap指令字节码自增变量案例4操作数栈自增变量案例5 自增变量 自增变量介绍 (1)自增变量是什么? i...
  • 1.关键字auto_increment2.自增用法例:CREATE TABLE animals ( id mediumint not null auto_increment,...3.关于自增Q:怎么获得当前的自增的最大值?Q:怎么获得table的当前自增最大值?A:select @@identityA:select ma...
  • 编号自增

    2019-06-18 09:19:41
    编号自增 给大家分享的功能是编号自增 编号自增的意思就是获取数据库的编号然后往上一个一个的递增 效果图: Html代码: 编号的文本框 MVC代码: public ActionResult EnumAddSelf()//编号自增 { string Enumber ...
  • Navicat中设置主键自增自增初始值

    万次阅读 2018-03-31 14:50:14
    1、设置主键自增2、设置主键自增初始值
  • 设置MySQL自增列的自增初值

    千次阅读 2017-11-07 09:41:07
    在许多类似的项目中,我们可能会把以前的数据库直接复制到新的项目中,但是有些表中的自增列都很大,后面插入数据会在此基础上递增,那么如果来设置自增的初值呢?
  • mysql 自增

    2019-03-20 16:19:45
    设置主键自增自增初始值 主键设定自动递增 选项里可以设定初始值 需要保证主键已有的值中不能大于设定的初始值
  • 自增与右自增的区别 左自增(++a) 和 右自增 (a++)的区别 ++和--既可以出现操作数的左边,也可以出现在右边,但结果是不同的 左自增例子: public class Demo { public static void main...
  • 对C++新手来说,对前自增和后自增操作符可能会有一些困惑,本文从重载自增操作符角度进行理解分析。
  • 书上说,对于C++中内建数据类型,前自增和后自增效率差别不大,对于自定义数据类型,后自增要返回对象的值并在原对象中自增,导致产生复制开销,引起效率降低。 问题:1、无论内建还是自定义数据类型,单条语句...
  • mycat 主键自增代码

    2019-04-29 18:00:17
    mycat 主键自增代码
  • 这两天在思考怎么生成数据库随机名称,思前想后觉得还是利用自增的逻辑主键是最方便快捷的,于是便尝试着获取一种自增的mysql函数自增mysql函数1 BEGIN2 DECLARE id INT DEFAULT 0;3 SELECT cuid + 1 INTO id from ...
  • 非主键自增,可以控制按照每天或者每月每年自增,可以控制位数,前缀后缀,返回值中间也可以按照要求拼接。数据库方式实现。
  • mybatis 自增主键配置mybatis自增主键配置(?)mybatis进行插入操作时,如果表的主键是自增的,针对不同的数据库相应的操作也不同。基本上经常会遇到的就是 Oracle Sequece 和 Mysql 自增主键,至于其他的手动生成唯一...
  • oracle创建自增列.txt

    2020-10-08 16:20:45
    oracle创建自增列.txtoracle创建自增列.txtoracle创建自增列.txtoracle创建自增列.txtoracle创建自增列.txtoracle创建自增列.txt
  • 如何实现MySQL设置自增字段是许多人都问到的问题,下面就为您介绍MySQL设置自增字段的相关知识,希望对您学习MySQL数据库能有所启迪。MySQL设置自增字段的相关语句:alter table album change ALBUM_ID ALBUM_ID ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 43,961
精华内容 17,584
关键字:

自增