返回顶部
首页 > 资讯 > 数据库 >怎么理解MYSQL的auto_increment_offset和auto_increment_increment值
  • 593
分享到

怎么理解MYSQL的auto_increment_offset和auto_increment_increment值

2024-04-02 19:04:59 593人浏览 独家记忆
摘要

本篇内容主要讲解“怎么理解Mysql的auto_increment_offset和auto_increment_increment值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让

本篇内容主要讲解“怎么理解Mysql的auto_increment_offset和auto_increment_increment值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解mysql的auto_increment_offset和auto_increment_increment值”吧!

实际上两个值是这样的:
我们理解auto_increment_offset为0开始的偏移量
auto_increment_increment是一个步长
auto_increment_offset+(N-1)*auto_increment_increment
N代表的是插入的次数。这算出来实际上是在0-+∽ 之间可以设置的值。
打个比方
mysql> set auto_increment_offset=2;
Query OK, 0 rows affected (0.00 sec)

mysql> set auto_increment_increment=5;
Query OK, 0 rows affected (0.00 sec)

这样我们允许的值是2  7  12 17 ....
我们建立一个表

mysql> create table testcr11(id int primary key auto_increment)  AUTO_INCREMENT=1;
Query OK, 0 rows affected (0.22 sec)
mysql> insert into testcr11 values(NULL);
Query OK, 1 row affected (0.01 sec)
mysql> select * from testcr11;
+----+
| id |
+----+
|  2 |
+----+
1 row in set (0.00 sec)

可以看到值并不是1开始而是2,在插入一行

mysql> insert into testcr11 values(NULL);
Query OK, 1 row affected (0.20 sec)
mysql> select * from testcr11;
+----+
| id |
+----+
|  2 |
|  7 |
+----+
2 rows in set (0.00 sec)
可以看到没有问题

但是问题是遇到如下一个提示:
When the value of auto_increment_offset is greater than that of
auto_increment_increment, the value of auto_increment_offset is ignored

也就是如果auto_increment_offset>auto_increment_increment ,auto_increment_offset将被忽略。
这个也可以理解,比如
auto_increment_offset = 10
auto_increment_increment = 5

按照公式我们第一次插入的值是10 15 20 ,但是我们发现在0-+∽这样一个线性范围内,我们丢掉了一个
这个值就是10-5 = 5,如果我们这样理解就理解得通了,但是事实真是这样吗?
我打开源码:
看到如下的计算方式
inline ulonglong
compute_next_insert_id(ulonglong nr,struct system_variables *variables)
{
  const ulonglong save_nr= nr;
  if (variables->auto_increment_increment == 1)
    nr= nr + 1; // optimization of the fORMula below
  else
  {
    nr= (((nr+ variables->auto_increment_increment -
           variables->auto_increment_offset)) /
         (ulonglong) variables->auto_increment_increment);
    nr= (nr* (ulonglong) variables->auto_increment_increment +
         variables->auto_increment_offset);
  }

  if (unlikely(nr <= save_nr))
    return ULLONG_MAX;
  return nr;
}


我使用了GDB进行断点调试如下:
(gdb) p nr
$1 = 0
(gdb) n
3479      if (variables->auto_increment_increment == 1)
(gdb) p save_nr
$2 = 0
(gdb) p variables->auto_increment_increment 
$3 = 5
(gdb) p variables->auto_increment_offset
$4 = 10
(gdb) n
3485             (ulonglong) variables->auto_increment_increment);
(gdb) p nr
$5 = 0
(gdb) n
3487             variables->auto_increment_offset);
(gdb) p nr
$6 = 3689348814741910322
(gdb) n
3490      if (unlikely(nr <= save_nr))
(gdb) p save_nr
$7 = 0
(gdb) p nr
$8 = 4
(gdb) n
3493      return nr;

这样我们找到了问题所在
(gdb) p nr
$6 = 3689348814741910322

这里
(((nr+ variables->auto_increment_increment -
           variables->auto_increment_offset)) /
         (ulonglong) variables->auto_increment_increment);
 variables->auto_increment_increment -
           variables->auto_increment_offset
这里出现了负数,但是运算的时候是无符号longlong类型,自动类型转换后得到
了一个非常大的
$6 = 3689348814741910322
这里出现了异常最后得到了一个数字 4
然后我们插入的就是4
mysql> select * from testcr5;
+----+
| id |
+----+
|  4 |
+----+
1 row in set (0.00 sec)

也许如果auto_increment_offset>auto_increment_increment会由于转换问题得到一个
不确定的结果干脆叫做
When the value of auto_increment_offset is greater than that of
auto_increment_increment, the value of auto_increment_offset is ignored
------------------------------------------------------------------------------------------------------------------
下面是具体计算过程:
如果我们要刨根问题为什么是4这个问题需要涉及到很多东西我们先来看变量的类型

先给出计算源码
  typedef unsigned long long ulonglong;
  typedef unsigned long ulong;
  
     nr= (((nr+ variables->auto_increment_increment -
           variables->auto_increment_offset)) /
         (ulonglong) variables->auto_increment_increment);
     
     nr= (nr* (ulonglong) variables->auto_increment_increment +
         variables->auto_increment_offset);
         
给出类型

 nr                                  (ulonglong *)  =0(初始)
 variables->auto_increment_increment (ulong *)  =5
 variables->auto_increment_offset    (ulong *)  =10 
 
 在64位linux上ULONG 和ULONGLONG都是8字节,所以我们认为他们表示的范围相同,他们则相同
 同时我们还需要知道ulonglong是不能存储负数的
 而variables->auto_increment_increment - variables->auto_increment_offset =-5 他转换为
 ulong正数就是 18446744073709551611 为什么是这么多呢?
 首先我们要看5的ulong的表示如下:
 0 0000000 00000000 00000000 00000000 00000000 00000000 00000000 00000101 最开始的是符号位
 反码
 0 1111111 11111111 11111111 11111111 11111111 11111111 1111111111111010 
 补码
 0 1111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011
 我们都没有动符号位,实际上负数的符号位是1所以是
 1 1111111 11111111 11111111 11111111 11111111 11111111 11111111 11111011
 好下面我们看看他的16进制表示
 FF FF FF FF FF FF FF FB 这就是-5long的表示,因为ULONG没有负数那么将符号位作为数字表示位
 那么转换为10进制实际上就是
 18446744073709551611
 下面是我GDB 出来的,因为小端Little_endian是不管在内存和磁盘中存储都是内存的低地址存储数值的低位数
 实际上0xfb    0xff    0xff    0xff    0xff    0xff    0xff    0xff 
 fb是低位
( Http://blog.itpub.net/7728585/viewspace-2124159/ 关于大端小端)
 (gdb) p test
$1 = 18446744073709551611
(gdb) p &test
$2 = (ulonglong *) 0x7fffffffea28
(gdb) x/8bx 0x7fffffffea28
0x7fffffffea28: 0xfb    0xff    0xff    0xff    0xff    0xff    0xff    0xff
既然
nr+ variables->auto_increment_increment = 18446744073709551611
我们来看下一步
/(ulonglong) variables->auto_increment_increment
实际上就是
18446744073709551611 / 5 = 3689348814741910322 
为什么是3689348814741910322 明显丢掉了一个1
实际上
3689348814741910322*5 = 18446744073709551610
因为整数是不能表示浮点数的,在C语言中使用丢弃小数点后的值。这里就丢了1,这其实就是为什么是4 而不是 5的原因
那么(初始的nr=0)
     nr= (((nr+ variables->auto_increment_increment -
           variables->auto_increment_offset)) /
         (ulonglong) variables->auto_increment_increment);
     nr = 3689348814741910322
接下来做的是
       nr= (nr* (ulonglong) variables->auto_increment_increment +variables->auto_increment_offset);       
nr* (ulonglong) variables->auto_increment_increment 我们已经说了他的值就是
       3689348814741910322*5 = 18446744073709551610
       然后 
       18446744073709551610+variables->auto_increment_offset
       就是
       18446744073709551610+10
       我来看一下 18446744073709551610 二进制
       11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111010
       10的二进制
       1010 低位相加       
       11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111010
       +                                                                  1010
       -----------------------------------------------------------------------
     1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100            
     我们明显的看到了溢出。溢出就抛弃掉了剩下就是
       00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000100
     就是十进制的4 。
 这就是4计算出来的原因。
 所以MYSQL官方文档使用一个忽略来表示,实际上是不确定的值如果        
 如果
 auto_increment_offset 远远大于 variables->auto_increment_increment
 比如auto_increment_offset=1000
     auto_increment_increment = 2
 那么只要
 nr+ variables->auto_increment_increment< variables->auto_increment_offset
 那么值都是不确定的这里的nr是存储上一次来的自增值,初始为0
 nr+ variables->auto_increment_increment - variables->auto_increment_offset
所以基于这个原因,建议大家注意auto_increment_increment 大于 auto_increment_offset
是必要的。 

下面是一个简单程序演示这个过程:

点击(此处)折叠或打开

  1. #include<stdio.h>


  2. typedef unsigned long long ulonglong;

  3. typedef unsigned long ulong;


  4. int main(void)

  5. {

  6.         ulonglong nr = 0;

  7.         ulonglong nr1;

  8.         ulong auto_increment_increment = 5;

  9.         ulong auto_increment_offset = 10;

  10.         ulonglong t1=-5;

  11.         ulonglong test1;

  12.         printf("ulonglong size is:%lu ulong size is:%lu\n",sizeof(unsigned long long),sizeof(unsigned long));

  13.         printf("nr init values is:%llu\n",nr);

  14.         printf("auto_increment_increment is:%lu\n",auto_increment_increment);

  15.         printf("auto_increment_offset is :%lu\n",auto_increment_offset);

  16.         nr= (((nr+ auto_increment_increment - auto_increment_offset))/(ulonglong)auto_increment_increment );

  17.         printf("-5 ulonglong is :%llu\n",t1);

  18.         printf("nr+ auto_increment_increment - auto_increment_offset))/(ulonglong)auto_increment_increment is:%llu\n",nr);

  19.         test1 = nr* (ulonglong)auto_increment_increment;

  20.         nr= (nr* (ulonglong)auto_increment_increment + auto_increment_offset);

  21.     printf("nr* (ulonglong)auto_increment_increment is: %llu\n",test1);

  22.         printf("last nr is: %llu\n",nr);


  23. }


跑一下如下:
ulonglong size is:8 ulong size is:8
nr init values is:0
auto_increment_increment is:5
auto_increment_offset is :10
-5 ulonglong is :18446744073709551611
nr+ auto_increment_increment - auto_increment_offset))/(ulonglong)auto_increment_increment is:3689348814741910322
nr* (ulonglong)auto_increment_increment is: 18446744073709551610
last nr is: 4

到此,相信大家对“怎么理解MYSQL的auto_increment_offset和auto_increment_increment值”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: 怎么理解MYSQL的auto_increment_offset和auto_increment_increment值

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

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

猜你喜欢
  • 怎么理解MYSQL的auto_increment_offset和auto_increment_increment值
    本篇内容主要讲解“怎么理解MYSQL的auto_increment_offset和auto_increment_increment值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让...
    99+
    2024-04-02
  • MySQL主主配置auto_increment_offset和auto_increment_increment参数的示例分析
    这篇文章主要为大家展示了“MySQL主主配置auto_increment_offset和auto_increment_increment参数的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下...
    99+
    2024-04-02
  • JS原始值和引用值怎么理解
    这篇文章主要介绍“JS原始值和引用值怎么理解”,在日常操作中,相信很多人在JS原始值和引用值怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JS原始值和引用值怎么理解”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-22
  • 怎么理解MySQL的2PC和3PC
    这篇文章主要介绍“怎么理解MySQL的2PC和3PC”,在日常操作中,相信很多人在怎么理解MySQL的2PC和3PC问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解My...
    99+
    2024-04-02
  • MySQL怎么查找某列的最大值和最小值
    要查找某列的最大值和最小值,可以使用以下查询语句: SELECT MAX(column_name) AS max_value...
    99+
    2024-03-06
    MySQL
  • 怎么理解Vue中的模板语法插值和指令
    本篇内容主要讲解“怎么理解Vue中的模板语法插值和指令”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么理解Vue中的模板语法插值和指令”吧!Vue有很多模板语法特别好用,就是在HTML中写一些...
    99+
    2023-06-25
  • 怎么理解MySQL的innodb_flush_method
    这篇文章主要讲解了“怎么理解MySQL的innodb_flush_method”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解MySQL的innodb...
    99+
    2024-04-02
  • 怎么理解MYSQL数据类型存储中数值型
    怎么理解MYSQL数据类型存储中数值型,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。探索MYSQL 数值类型的存储,以及解读方...
    99+
    2024-04-02
  • javascript中的等值比较怎么理解
    本篇内容介绍了“javascript中的等值比较怎么理解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • PaddlePaddle框架怎么处理缺失值和异常值
    在PaddlePaddle框架中,处理缺失值和异常值的方法通常包括以下几种: 缺失值处理:通常可以使用均值、中位数、众数等方式填...
    99+
    2024-03-07
    PaddlePaddle
  • MySQL中怎么处理无效数据值
    MySQL中怎么处理无效数据值,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。  MySQL如何处理无效数据值  默认情况下,M...
    99+
    2024-04-02
  • 怎么理解MySQL中的MVCC
    这篇文章将为大家详细讲解有关怎么理解MySQL中的MVCC,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。关系数据库管理系统使用MVCC(Multiversi...
    99+
    2024-04-02
  • 怎么理解MySQL中的table_id
    本篇内容介绍了“怎么理解MySQL中的table_id”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一 t...
    99+
    2024-04-02
  • 怎么理解MySQL的Insert buffer
    本篇内容介绍了“怎么理解MySQL的Insert buffer”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成...
    99+
    2024-04-02
  • MySQL中的锁怎么理解
    本篇内容主要讲解“MySQL中的锁怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL中的锁怎么理解”吧!01. 怎么认识"锁"...
    99+
    2024-04-02
  • mysql平均值怎么来的
    mysql 中的平均值是数字总和除以数量。可以通过 avg() 函数计算,该函数不包含 null 值,并忽略所有负数值。 MySQL 平均值的计算 MySQL 中的平均值表示一组数字的...
    99+
    2024-05-30
    mysql
  • 怎么理解MySQL垂直和水平切分
    这篇文章主要介绍“怎么理解MySQL垂直和水平切分”,在日常操作中,相信很多人在怎么理解MySQL垂直和水平切分问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解MySQ...
    99+
    2024-04-02
  • MySQL持久化和回滚该怎么理解
    这篇文章跟大家分析一下“MySQL持久化和回滚该怎么理解”。内容详细易懂,对“MySQL持久化和回滚该怎么理解”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一...
    99+
    2024-04-02
  • mysql中bit类型怎么赋值和使用
    在 MySQL 中,BIT 类型用于存储位字段值。BIT(n) 表示 n 个位字段值,其中 n 是一个范围从 1 到 64 的整数。...
    99+
    2024-04-09
    mysql
  • 如何理解ol和ul的padding和margin默认值
    本篇内容主要讲解“如何理解ol和ul的padding和margin默认值”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解ol和ul的padding和mar...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作