• ADADADADAD

    MySQL自增列主从不一致的测试(r12笔记第37天)[ mysql数据库 ]

    mysql数据库 时间:2024-12-03 12:12:56

    作者:文/会员上传

    简介:

    MySQL里面有一个问题尤其值得注意,那就是自增列的重复值问题,之前也简单分析过一篇,但是在后续我想了下,还有很多地方需要解释,一个就是从库的自增列是如何维护的,是否重启从库,自

    以下为本文的正文内容,内容仅供参考!本站为公益性网站,复制本文以及下载DOC文档全部免费。

    MySQL里面有一个问题尤其值得注意,那就是自增列的重复值问题,之前也简单分析过一篇,但是在后续我想了下,还有很多地方需要解释,一个就是从库的自增列是如何维护的,是否重启从库,自增列会受到影响。

    我们继续来测试一下。首先复现这个问题。

    创建表t1,插入3行数据。

    use test;
    [test]> drop table if exists t1;
    Query OK, 0 rows affected, 1 warning (0.01 sec)
    > create table t1(id int auto_increment, a int, primary key (id)) engine=innodb;
    Query OK, 0 rows affected (0.02 sec)
    insert into t1 values (1,2);
    insert into t1 values (null,2);
    insert into t1 values (null,2);
    [test]> select *from t1;
    +----+------+
    | id | a |
    +----+------+
    | 1 | 2 |
    | 2 | 2 |
    | 3 | 2 |
    +----+------+因为存在3行数据,这个时候自增列的值是4.

    [test]> show create table t1\G
    *************************** 1. row ***************************
    Table: t1
    Create Table: CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)我们删除id值最大的记录id=3

    mysql> delete from t1 where id=3;
    Query OK, 1 row affected (0.02 sec)这个时候会发现AUTO_INCREMENT=4的值不会有任何变化。

    我们来挖掘一下binlog的内容,就会发现insert语句很特别。

    # /usr/local/mysql_5.7.17/bin/mysqlbinlog --socket=/home/data/s1/s1.sock --port=24801 -vv /home/data/s1/binlog.000001可以看到insert语句是MySQL独有的语法形式。
    ### SET
    ### @1=3 /* INT meta=0 nullable=0 is_null=0 */
    ### @2=2 /* INT meta=0 nullable=1 is_null=0 */
    # at 2271

    delete也会基于行级变更,定位到具体的记录的方式来删除。

    ### DELETE FROM `test`.`t1`
    ### WHERE
    ### @1=3 /* INT meta=0 nullable=0 is_null=0 */
    ### @2=2 /* INT meta=0 nullable=1 is_null=0 */
    # at 2509
    我们重启一下数据库。

    # mysqladmin --socket=/home/data/s1/s1.sock --port=24801 shutdown
    # /bin/sh /usr/local/mysql_5.7.17/bin/mysqld_safe --defaults-file=/home/data/s1/s1.cnf &重启之后就会发现情况发生了变化,原来的自增值4现在变为了3,这个也是基于max(id)+1的方式来计算的。

    mysql> show create table t1\G
    *************************** 1. row ***************************
    Table: t1
    Create Table: CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)这个时候我们来关注一下从库,从库的自增列值会变化吗?
    mysql> show create table t1\G
    *************************** 1. row ***************************
    Table: t1
    Create Table: CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)这个时候就会发现重启数据库以后,主从的自增列的值不同了。
    那么我们来进一步测试,在主库插入一条记录,这样自增列的值就是4.

    mysql> insert into t1 values (null,2);
    Query OK, 1 row affected (0.01 sec)自增列的值为4,而从库的自增列的值依旧没有任何变化。

    继续插入一条记录,这个时候主库的自增列就会是5

    mysql> insert into t1 values (null,2);
    Query OK, 1 row affected (0.00 sec)而从库呢,这个时候自增列会持续发生变化吗?我们来验证一下,这个时候从库的自增列又开始生效了。

    mysql> show create table t1\G
    *************************** 1. row ***************************
    Table: t1
    Create Table: CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)
    还有一点需要注意,那就是指定了自增列的值,这一点上和Oracle有一定的差距,但是又很相似。
    这个时候数据库主库中的数据如下:

    mysql> select * from t1;
    +----+------+
    | id | a |
    +----+------+
    | 1 | 2 |
    | 2 | 2 |
    | 3 | 2 |
    | 4 | 2 |
    | 5 | 2 |
    +----+------+
    5 rows in set (0.00 sec)为了方便测试,我们继续插入一条数据,这一次我指定了id值。

    mysql> insert into t1 values(6,2);
    Query OK, 1 row affected (0.00 sec)让人感到安慰的是,这张情况下自增列还是会持续增加。

    mysql> show create table t1\G
    *************************** 1. row ***************************
    Table: t1
    Create Table: CREATE TABLE `t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `a` int(11) DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
    1 row in set (0.00 sec)此时查看从库,这个自增列也还是7,,
    通过这个案例,我们能够看到在MySQL会存在这样一类问题,实际上在多环境历史数据归档的情况下,如果主库重启,很可能会出现数据不一致的情况。

    我也在MySQL的官方bug列表中看到很多人在讨论这个问题,看来很多人碰到这个坑。而这个问题其实细究起来实现也不是一个很繁琐的工作,为什么一直没有修复。

    这个问题在MySQL很久以前就有,在现在依旧存在,什么时候会修复呢,根据官方的计划会在8.0中修复。让我们拭目以待。



    MySQL自增列主从不一致的测试(r12笔记第37天).docx

    将本文的Word文档下载到电脑

    推荐度:

    下载
    热门标签: 37天r12笔记