问题现象:

Mysql插入一条数据时,未指定自增键的值却报错:自增键重复,无法插入!

执行SQL

INSERT INTO `test`.`test_sort`(`id`, `name`, `age`, `birthday`) VALUES
(10027, '测试', 23, '2020-01-07 12:23:11')

报错:

INSERT INTO `test`.`test_sort`(`id`, `name`, `age`, `birthday`) VALUES
(10027, '测试', 23, '2020-01-07 12:23:11')
> 1062 - Duplicate entry '38' for key 'sort'
> 时间: 0.001s

表的创建语句:

CREATE TABLE `test_sort`  (
`id` int(11) NOT NULL COMMENT '主键',
`name` varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
`age` tinyint(3) UNSIGNED NULL DEFAULT NULL COMMENT '年龄',
`birthday` datetime(0) NULL DEFAULT NULL COMMENT '生日',
`sort` int(11) NOT NULL AUTO_INCREMENT COMMENT '序号',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `sort`(`sort`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;

这里可以发现,sort字段在表中是自增键,通过唯一索引 sort 来实现,而我在插入新行的时候没有指定 sort 字段的值,那么它理论上会采用当前自增 B-Tree 上最大数字 + 1,这里却提示他冲突了。

问题还原

表里面原来的数据如下:

INSERT INTO `test_sort` VALUES (10001, '张三', 23, '2020-01-07 12:23:11', 1);
INSERT INTO `test_sort` VALUES (10002, '王五', 23, '2020-01-07 12:23:11', 9);
INSERT INTO `test_sort` VALUES (10003, '赵六', 23, '2020-01-07 12:23:11', 10);
INSERT INTO `test_sort` VALUES (10004, '钱七', 23, '2020-01-07 12:23:11', 11);
INSERT INTO `test_sort` VALUES (10005, '刘八', 23, '2020-01-07 12:23:11', 12);
INSERT INTO `test_sort` VALUES (10006, '冯九', 23, '2020-01-07 12:23:11', 13);
INSERT INTO `test_sort` VALUES (10007, '李四', 23, '2020-01-07 12:23:11', 44);
INSERT INTO `test_sort` VALUES (10008, '李四1', 23, '2020-01-07 12:23:11', 36);
INSERT INTO `test_sort` VALUES (10009, '王五1', 23, '2020-01-07 12:23:11', 38);
INSERT INTO `test_sort` VALUES (10010, '赵六1', 23, '2020-01-07 12:23:11', 40);
INSERT INTO `test_sort` VALUES (10011, '钱七1', 23, '2020-01-07 12:23:11', 41);
INSERT INTO `test_sort` VALUES (10012, '刘八1', 23, '2020-01-07 12:23:11', 46);
INSERT INTO `test_sort` VALUES (10013, '冯九1', 23, '2020-01-07 12:23:11', 47);
INSERT INTO `test_sort` VALUES (10014, '李四1', 23, '2020-01-07 12:23:11', 48);
INSERT INTO `test_sort` VALUES (10015, '王五1', 23, '2020-01-07 12:23:11', 21);
INSERT INTO `test_sort` VALUES (10016, '赵六1', 23, '2020-01-07 12:23:11', 22);
INSERT INTO `test_sort` VALUES (10017, '钱七1', 23, '2020-01-07 12:23:11', 23);
INSERT INTO `test_sort` VALUES (10018, '刘八1', 23, '2020-01-07 12:23:11', 24);
INSERT INTO `test_sort` VALUES (10019, '冯九1', 23, '2020-01-07 12:23:11', 25);
INSERT INTO `test_sort` VALUES (10021, '测试', 23, '2020-01-07 12:23:11', 28);
INSERT INTO `test_sort` VALUES (10022, '测试', 23, '2020-01-07 12:23:11', 30);
INSERT INTO `test_sort` VALUES (10023, '测试', 23, '2020-01-07 12:23:11', 32);
INSERT INTO `test_sort` VALUES (10024, '测试', 23, '2020-01-07 12:23:11', 33);
INSERT INTO `test_sort` VALUES (10025, '测试', 23, '2020-01-07 12:23:11', 34);
INSERT INTO `test_sort` VALUES (10026, '测试', 23, '2020-01-07 12:23:11', 37);

这里在数据插入时,我通过 Navicat 手动修改了表中 sort 字段的值,改成一个比原来最大值。此时再重新添加数据,当自增键的值增长到该值时,就会报该错误。

解决方法

删除原来用于自增的唯一索引 sort,然后重新创建该索引。记得删除后点保存,之后添加索引,保存

删除时出现该提示是因为自增长必须依赖索引存在,索引应该先去掉该键的自增长功能。在重新添加索引后打开该功能

受《高性能Mysql》的启发

这本书里面有句:通过一个不做任何操作的 ALTER 操作来重建表。而我们的删除-重新添加操作和他有异曲同工之妙。

启发

这次问题给我带来的启发如下,也请同行们参考

  1. 不到万不得已不要手动去修改数据库的唯一索引字段
  2. 如果修改了,修改之后通过删除 + 重新添加索引的方式避免线上服务出错
  3. 书中自有黄金屋,如果不是之前读过自增键、索引相关的知识,遇到此事便不能及时解决,可能会造成无法挽回的损失,书到用时方恨少...

Mysql唯一索引线上故障记录的更多相关文章

  1. MySQL慢日志线上问题分析及功能优化

    本文来源于数据库内核专栏. MySQL慢日志(slow log)是MySQL DBA及其他开发.运维人员需经常关注的一类信息.使用慢日志可找出执行时间较长或未走索引等SQL语句,为进行系统调优提供依据 ...

  2. MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)

    公司线上在用partition,有一个表的分区字段错了,需要重建,结果发现没有办法像修改主键字段或者修改索引字段那样直接一条sql搞定.而是需要建临时表,有down time,所以去仔细看了文档,研究 ...

  3. mysql 唯一索引与null.md

    mysql 的唯一索引要求所有参与的列都不能够为 null 值,如果唯一索引中的任何一个元素含有 null 值,则唯一约束将不起作用. 示例代码 create table tb ( a int, b ...

  4. mysql 唯一索引UNIQUE使用方法详解

    创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复.唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值.如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的 ...

  5. MySQL死锁系列-线上死锁问题排查思路

    前言 MySQL 死锁异常是我们经常会遇到的线上异常类别,一旦线上业务日间复杂,各种业务操作之间往往会产生锁冲突,有些会导致死锁异常.这种死锁异常一般要在特定时间特定数据和特定业务操作才会复现,并且分 ...

  6. 【MySQL】实现线上千万数据表添加字段操作以及缓存刷新

    需求背景: 由于业务需求,需要在线上用户表添加渠道字段,用于区分不同渠道注册的用户,目前该表有20+个字段,8个索引 线上用户数据大概1500W左右,需要不停机增加数据库字段,同时需要刷新Redis缓 ...

  7. MySQL数据库如何线上修改表结构

    一.MDL元数据锁 在修改表结构之前,先来看下可能存在的问题. 1.什么是MDL锁 MySQL有一个把锁,叫做MDL元数据锁,当对表修改的时候,会自动给表加上这把锁,也就是不需要自己显式使用. 当对表 ...

  8. 关于Mysql唯一索引的操作方法(添加删除)

    首先我们查看一下News数据表的索引信息      使用命令 show index from ‘数据表名称’; 目前数据表中仅有一个主键索引 继续,我们给news表添加两个唯一索引(两种方法) 方法一 ...

  9. MySQL数据库索引(上)

    上一篇回顾: 1.数据页由七部分组成,包括File Header(描述页的信息).Page Header(描述数据的信息).Infimum + Supremum(页中的虚拟数据最大值和最小值).Use ...

随机推荐

  1. oracle函数 current_date

    [功能]:返回当前会话时区中的当前日期 [参数]:没有参数,没有括号 [返回]:日期 [示例]select current_date from dual; 返回:2008-11-14

  2. LInux下编译发生的libc相关错误

    在某主机上编译程序,发生有找不到libc的问题,自己写了个简单的hello world程序,编译也失败,报错如下: # gcc -o 1 1.c /usr/bin/ld: skipping incom ...

  3. @codeforces - 117C@ Cycle

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个竞赛图(有向完全图),请找出里面的某个三元环,或者判断不 ...

  4. CSS长度单位:px和pt的区别

    先搞清基本概念:px就是表示pixel,像素,是屏幕上显示数据的最基本的点:而pt就是point,是印刷行业常用单位,等于1/72英寸. 这样很明白,px是一个点,它不是自然界的长度单位,谁能说出一个 ...

  5. Laravel如何引用第三方(自定义)库

    想做一个网页抓取的功能,底层使用php的laravel框架. 这里使用phpQuery库来实现网页抓取,这里不做介绍. 需要了解的可以百度,或者等我填坑. 下载最新版本可以前往https://code ...

  6. 谷歌BERT预训练源码解析(一):训练数据生成

    目录预训练源码结构简介输入输出源码解析参数主函数创建训练实例下一句预测&实例生成随机遮蔽输出结果一览预训练源码结构简介关于BERT,简单来说,它是一个基于Transformer架构,结合遮蔽词 ...

  7. ccf-201703-4-地铁修建

    二分+并查集 发现了一个很奇怪的问题,二分的上界设置错了,结果是运行错误...只有95分.后来改了上界就100了,百思不得其解 #include<cstdio> #include<c ...

  8. 关于DOM的一些基础问题

    什么是 DOM? DOM 是一项 W3C (World Wide Web Consortium) 标准,全称是文档对象模型(Document Object Model). DOM 定义了访问文档的标准 ...

  9. 下推栈实现(c++编程思想 p136)

    1 头文件Stack.h #ifndef STACK_H #define STACK_H struct Stack { struct Link { void* data; Link* next; vo ...

  10. 154th LeetCode Weekly Contest

    A B D均比较简单.先说C题 K-Concatenation Maximum Sum Given an integer array arr and an integer k, modify the ...