Mysql唯一索引线上故障记录
问题现象:
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 操作来重建表。而我们的删除-重新添加操作和他有异曲同工之妙。
启发
这次问题给我带来的启发如下,也请同行们参考
- 不到万不得已不要手动去修改数据库的唯一索引字段
- 如果修改了,修改之后通过删除 + 重新添加索引的方式避免线上服务出错
- 书中自有黄金屋,如果不是之前读过自增键、索引相关的知识,遇到此事便不能及时解决,可能会造成无法挽回的损失,书到用时方恨少...
Mysql唯一索引线上故障记录的更多相关文章
- MySQL慢日志线上问题分析及功能优化
本文来源于数据库内核专栏. MySQL慢日志(slow log)是MySQL DBA及其他开发.运维人员需经常关注的一类信息.使用慢日志可找出执行时间较长或未走索引等SQL语句,为进行系统调优提供依据 ...
- MySQL 分区表 partition线上修改分区字段,后续进一步学习partition (1)
公司线上在用partition,有一个表的分区字段错了,需要重建,结果发现没有办法像修改主键字段或者修改索引字段那样直接一条sql搞定.而是需要建临时表,有down time,所以去仔细看了文档,研究 ...
- mysql 唯一索引与null.md
mysql 的唯一索引要求所有参与的列都不能够为 null 值,如果唯一索引中的任何一个元素含有 null 值,则唯一约束将不起作用. 示例代码 create table tb ( a int, b ...
- mysql 唯一索引UNIQUE使用方法详解
创建唯一索引的目的不是为了提高访问速度,而只是为了避免数据出现重复.唯一索引可以有多个但索引列的值必须唯一,索引列的值允许有空值.如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的 ...
- MySQL死锁系列-线上死锁问题排查思路
前言 MySQL 死锁异常是我们经常会遇到的线上异常类别,一旦线上业务日间复杂,各种业务操作之间往往会产生锁冲突,有些会导致死锁异常.这种死锁异常一般要在特定时间特定数据和特定业务操作才会复现,并且分 ...
- 【MySQL】实现线上千万数据表添加字段操作以及缓存刷新
需求背景: 由于业务需求,需要在线上用户表添加渠道字段,用于区分不同渠道注册的用户,目前该表有20+个字段,8个索引 线上用户数据大概1500W左右,需要不停机增加数据库字段,同时需要刷新Redis缓 ...
- MySQL数据库如何线上修改表结构
一.MDL元数据锁 在修改表结构之前,先来看下可能存在的问题. 1.什么是MDL锁 MySQL有一个把锁,叫做MDL元数据锁,当对表修改的时候,会自动给表加上这把锁,也就是不需要自己显式使用. 当对表 ...
- 关于Mysql唯一索引的操作方法(添加删除)
首先我们查看一下News数据表的索引信息 使用命令 show index from ‘数据表名称’; 目前数据表中仅有一个主键索引 继续,我们给news表添加两个唯一索引(两种方法) 方法一 ...
- MySQL数据库索引(上)
上一篇回顾: 1.数据页由七部分组成,包括File Header(描述页的信息).Page Header(描述数据的信息).Infimum + Supremum(页中的虚拟数据最大值和最小值).Use ...
随机推荐
- @loj - 2290@ 「THUWC 2017」随机二分图
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一个左右各 n 个点的二分图,图中的边会按照一定的规律随机出现. ...
- ListOfOpenSourcePrograms
ListOfOpenSourcePrograms Contents Desktop Applications Communication Engineering Educational Financi ...
- 为 Ubuntu 18.04 添加开机自动加载 ntfs分区 功能
注意:Ubuntu终端命令是区分大小写的 1,准备的: ntfs-3g -- 提供ntfs读写支持(一般说来是自带的,若没有,可是使用 sudo apt-get isntall ntfs-3g ...
- WOE:信用评分卡模型中的变量离散化方法(生存分析)
WOE:信用评分卡模型中的变量离散化方法 2016-03-21 生存分析 在做回归模型时,因临床需要常常需要对连续性的变量离散化,诸如年龄,分为老.中.青三组,一般的做法是ROC或者X-tile等等. ...
- mysql基础(库、表相关)
一. mysql支持的数据类型 1.1 mysql支持的数字类型: TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767 ...
- python编程之进程
进程:运行中的程序 进程和操作系统的关系:进程是操作系统调度和资源分配的最小单位,是操作系统的结构基础. 那么为什么要有进程呢? 程序在运行时,会使用各种硬件资源,如果他们之间没有界限,那么程序之间的 ...
- python基础十四之匿名函数
匿名函数 处理简单问题的简化函数,关键字lambda. # 格式:函数名 = lambda 参数:返回值 anonymity = lambda s: s ** 0.5 print(anonymity( ...
- java 事件监听机制组成
事件源(组件) 事件(Event) 监听器(Listener) 事件处理(引发事件后处理方式) 事件监听机制流程图 务必记牢: 确定事件源(容器或组件) 通过事件源对象的addXXXListener( ...
- wpf passwobox 添加水印
之前有做过wpf texbox添加水印,这个并不难 重写一下样式就可以了,今天用到了passwordbox 添加水印的时候 发现还是有点难度的. 这个难度就在于如何去取password的长度来控制水印 ...
- Visio文本相关操作
三种方式:双击形状输入文本,插入文本框, 文本工具 文本块工具 选择后可以对文本进行移动旋转 如果要给文本加入边框 直接显示线条就可以了 因为都是文本框 添加特殊文本: 插入符号 插入域 比如当前时间 ...