问题现象:

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. 解决大数据难题 阿里云MaxCompute获科技大奖

    摘要: 据介绍,MaxCompute(大规模分布式的数据计算平台)是国内最早自研的大数据计算平台之一,主要应用于大规模数据处理场景.目前,这项源自浙江.解决世界级难题的成果已拥有EB(百京)级别的数据 ...

  2. 通过GDB重新获得进程的输出

    有时通过SecureCRT或者Putty远程ssh到主机上执行某个进程,因长时间没有交互导致ssh断链,此时该进程由init进程收留.该进程的输出也就无法获得了. 这种情况下,可以利用gdb重新获得该 ...

  3. POJ2976 题解 0/1分数规划入门题 二分

    题目链接:http://poj.org/problem?id=2976 关于 0/1分数规划 参见 这篇博客 实现代码如下: #include <cstdio> #include < ...

  4. fastclick使用与 fastclick ios11.3相关bug原因(ios输入框点击变得不灵敏,ios input失焦后,页面上移,点击不了)

    FastClick 移动设备上的浏览器默认会在用户点击屏幕大约延迟300毫秒后才会触发点击事件,这是为了检查用户是否在做双击.为了能够立即响应用户的点击事件,就有了FastClick. 安装fastc ...

  5. H3C PPP MP配置示例二

  6. 2019-9-2-给博客添加rss订阅

    title author date CreateTime categories 给博客添加rss订阅 lindexi 2019-09-02 12:57:38 +0800 2018-2-13 17:23 ...

  7. [C++] 检查随机内存溢出

    C++程序的随机内存溢出是非常难处理的,windows提供了一些工具来缓解这个问题. windows debuger提供的Global Flags可以设置"enable heap tail ...

  8. P1067 叠罗汉

    题目描述 茜茜和聪聪是关系很好的同桌,有一天,茜茜觉得天空中的白云像棉花糖一样,应该很好吃吧,但是够不着,她很烦恼. 聪聪为了帮助茜茜解决烦恼,决定帮他把天空中的白云摘下来做成棉花糖给她吃. 但是聪聪 ...

  9. Java 9版本之后Base64Encoder和Base64Decoder无法继续使用解决办法

    在项目开发过程中,因为重装系统,安装了Java10版本,发现sun.misc.Base64Encoder和sun.misc.Base64Decoder无法使用. 原因: 查看官网发现,JDK中的/li ...

  10. ASP.NET MVC 实现页落网资源分享网站+充值管理+后台管理(9)之系统登录

    前面我们已经做好了一个文章管理功能模块,接下来,我们回头来做登录窗口,登录不仅涉及到登录验证还涉及到登录日志还有缓存时长等. 对于缓存的相关设置,我们已经写好封装在Bobo.Utilities.dll ...