问题背景

最近线上遇到一个问题,用户重启实例后发现有张表打不开了,经调研后发现是用户之前的霸蛮操作导致的,下面给出复现步骤:

create table t1 (id int not null primary key, name varchar(100) not null) engine=innodb;

create table t2 (id int not null primary key, fid int not null, name varchar(100) not null, CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)) engine=innodb;

insert into t1 values(1, "test 1"),(2, "test 2"),(3,"test 3");

insert into t2 values(1, 1, "test 1"),(2, 1, "test 2"),(3, 2, "test 3");

show create table t2;

show create table t2G

*************************** 1. row ***************************

Table: t2

Create Table: CREATE TABLE `t2` (

`id` int(11) NOT NULL,

`fid` int(11) NOT NULL,

`name` varchar(100) NOT NULL,

PRIMARY KEY (`id`),

KEY `fk_fid` (`fid`),

CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1

-- 霸蛮的删掉外键约束用的索引

set foreign_key_checks=off;

alter table t2 drop index `fk_fid`;

-- 重启mysqld前表t2正常

set foreign_key_checks=on;

show create table t2;

*************************** 1. row ***************************

Table: t2

Create Table: CREATE TABLE `t2` (

`id` int(11) NOT NULL,

`fid` int(11) NOT NULL,

`name` varchar(100) NOT NULL,

PRIMARY KEY (`id`),

CONSTRAINT `fk_fid` FOREIGN KEY (`fid`) REFERENCES `t1` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1

-- 重启mysqld

show tables;

+----------------+

| Tables_in_test |

+----------------+

| t1 |

| t2 |

+----------------+

show create table t2;

ERROR 1146 (42S02): Table "test.t2" doesn"t exist

重启后t2表打不开了。

问题分析

在MySQL中,为了能够快速的检查外键约束,需要子表和父表对应的列上都要有索引,如果对应字段上没有索引, 子表在建立外键约束的时候,会自动加上。

MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist.

子表上的外键索引正常情况是删不掉,如果试图去删除的话会报错:

ERROR 1553 (HY000): Cannot drop index "fk_fid": needed in a foreign key constrain

删索引时的外键检查逻辑在 innobase_check_foreign_key_index()函数中,感兴趣的同学可以自己看下,调用栈如下:

#0 innobase_check_foreign_key_index

#1 ha_innobase::prepare_inplace_alter_table

#2 handler::ha_prepare_inplace_alter_table

#3 mysql_inplace_alter_table

#4 mysql_alter_table

#5 Sql_cmd_alter_table::execute

#6 mysql_execute_command

#7 mysql_parse

#8 dispatch_command

#9 do_command

#10 do_handle_one_connection

#11 handle_one_connection

#12 pfs_spawn_thread

#13 start_thread

#14 clone

但是如果用户设置了 set foreign_key_checks=off 后,删除索引时就不会进入 innobase_check_foreign_key_index() ,所以索引能被删掉。

在上面的复现步骤中还可以看到,如果不重启的话,表是能正常打开的,即使是做了flush tables,表也能正常打开,这又是为什么呢?

我们知道MySQL有个table_open_cache,这是server层对打开表的缓存,flush tables会把这个cache清掉;InnoDB层的字典系统对打开的表也有一个缓存,基于这个缓存又构建了2个链表dict_sys->table_LRU 和 dict_sys->table_non_LRU,位于前者中的表缓存会被系统用LRU算法清理掉,后者不会,清理由InnoDB后台线程做,flush tables 不会触发清理。并且如果InnoDB表有外键的话,缓存是被放在dict_sys->table_non_LRU上的,所以不会被后台线程清理掉,因此成功打开一次后就不会出问题了。关于含外键表缓存被放在 dict_sys->table_non_LRU上,具体的调用栈如下:

#0 dict_table_move_from_lru_to_non_lru

#1 dict_foreign_add_to_cache

#2 dict_load_foreign

#3 dict_load_foreigns

#4 dict_load_table

#5 dict_table_open_on_name

#6 ha_innobase::open

#7 handler::ha_open

#8 open_table_from_share

#9 open_table

#10 open_and_process_table

#11 open_tables

#12 open_tables

#13 mysqld_show_create

#14 mysql_execute_command

#15 mysql_parse

#16 dispatch_command

#17 do_command

#18 do_handle_one_connection

#19 handle_one_connection

#20 pfs_spawn_thread

#21 start_thread

#22 clone

关于这点官方文档也有描述:

InnoDB system table instances and parent and child table instances with foreign key relationships are not placed on the LRU list and are not subject to eviction from memory.

问题解决

通过上面的分析可以看出之所以表打不开,是因为用户霸蛮的删除了外键依赖的索引,但是能让用户通过SQL就把表弄的不能访问,也算是数据库系统的bug,也早有人给官方提了bug,详见bug#68148、bug#70260、bug#74659。

MySQL 5.6.12 对此进行了修复,如果遇到这种情况表打不开的话,只需要先 set foreign_key_checks=off,然后表就可以打开了,这时把缺失的索引再加上就可以了,修复详情见patch。

上面的修复是在出问题后,其实最好是能从源头上杜绝,不让用户删除外键约束需要的索引,因为这本身就是错误的操作,因此MySQL 5.7.5又出了一个patch,让用户无法删除外键约束的索引,即使用 set foreign_key_checks=off 关闭掉外键约束检查。

rds mysql 表被删了_MySQL · 捉虫动态 · 删除索引导致表无法打开相关推荐

  1. MySQL内核月报 2014.09-MySQL· 捉虫动态·auto_increment

    背景: Innodb引擎使用B_tree结构保存表数据,这样就需要一个唯一键表示每一行记录(比如二级索引记录引用). Innodb表定义中处理主键的逻辑是: 1.如果表定义了主键,就使用主键唯一定位一 ...

  2. MySQL内核月报 2014.10-MySQL· 捉虫动态·binlog重放失败

    背景 在 MySQL 日常维护中,要回滚或者恢复数据,我们经常会用 binlog 来在数据库上重放,执行类似下面的语句: mysqlbinlog mysql-bin.000001 | mysql -h ...

  3. mysql数据库表删了重建error_数据库内核月报 - 2015 / 09-MySQL · 捉虫动态 · 建表过程中crash造成重建表失败-阿里云开发者社区...

    问题描述 主库的create table语句传到备库,备库SQL线程执行过程中报错: Error 'Can't create table 'XXX.XX' (errno: -1)' on query. ...

  4. mysql创建表时添加范式_MySql三大范式与数据库设计和表创建常用语句

    [数据库设计的三大范式] 1.第一范式(1NF First Normal Fromate):数据表中的每一列(字段),必须是不可拆分的最小单元.也就是确保每一列的原子性. 例如: userInfo: ...

  5. mysql显示表的所有列车_MySQL中查看当前数据库的所有表

    关键词 MySQL数据库 表 摘要 本文介绍在MySQL数据库中,如何列出并查看当前数据库的所有表. 本文介绍在MySQL数据库中,如何列出并查看当前数据库的所有表. 我们创建一个数据库之后,数据库里 ...

  6. 怎样知道mysql的驱动是什么_MySQL连接查询到底什么是驱动表?看了这里你应该就明白了...

    作者:阿伟~ 链接:https://www.cnblogs.com/sy270321/p/12760211.html 准备我们需要的表结构和数据 两张表 studnet(学生)表和score(成绩)表 ...

  7. MySQL · 捉虫动态 · UK 包含 NULL 值备库延迟分析

    前言 在之前的月报 RDS 只读实例延迟分析 中,我们介绍了一些常见的备库延迟的场景,今天给大家分享一个比较少见的特殊场景. 简单的来说,就是在 UK 索引中存在大量 NULL 值情况下,如果备库选用 ...

  8. MySQL · 捉虫动态 · event_scheduler 慢日志记错

    问题背景 最近遇到了 event_scheduler 在记录慢日志时的一个 bug,在这里分享给大家. 为了方便描述问题,先构造一个简单的 event,如下: delimiter // create ...

  9. mysql数据库从删库到跑路之mysq索引

    一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...

最新文章

  1. [高中作文赏析]假如真的有时光隧道
  2. 【多标签文本分类】HFT-CNN: Learning Hierarchical Category Structure for Multi-label Short Text Categorization
  3. tsp问题 python_ortools tsp问题
  4. python、语言的主网站网址是-国产编程语言木兰被网友扒皮:原来是Python语言打包...
  5. 【网址收藏】k8s zookeeper-operator示例
  6. code删除前两个_听说用python来批量删除说说也挺快乐的呢~
  7. hazelcast入门教程_Hazelcast入门指南第7部分
  8. codeforces Labyrinth
  9. mysql操作数据库
  10. linux天气软件,类似智能手机!Linux中安装Conky天气插件
  11. nodejs随笔(二)
  12. 全网首发:FreeSwitch服务器转发引起的硬解失败原因分析
  13. C++ OpenCV 开发笔记整理分类合集【所有的相关记录,都整理在此】
  14. 2019汤家凤高等数学强化班讲义
  15. 应用时间序列分析案例操作--基于SAS软件,以北京市1980-2009年降水量为对象
  16. 什么是收缩压和舒张压?
  17. 巴菲特致股东的信pdf_巴菲特历年股东大会股东信问答实录集合(共7份)
  18. FRM-91500: Unable to start/complete the build.
  19. 软件设计师的证书有多少含金量?
  20. 苹果8参数_苹果12pro max 128G新起点预售价9099元-苹果 iPhone 12 Pro Max_西安手机行情...

热门文章

  1. 速成pytorch学习——6天Dataset和DataLoader
  2. 熬了几个大夜,学完一套985博士总结的Pytorch学习笔记(20G高清/PPT/代码)
  3. LambdaLoss | Google排序学习优化框架
  4. 中级病案信息技术计算机基础知识要点,病案信息技术基础知识考试重点梳理(最新最全).doc...
  5. 挑战Tiktok,跨境卖家的新红利流量渠道?
  6. signature=c0c1b69f720d190a4a817d6bf2ff57c3,Fungicidal substituted N-(1-iodopropargyl)thiazolidinones
  7. vscode如何自定义补全内容,自定义常用的快捷方式?
  8. ROS入门-5.认识ROS及ROS的基本概念
  9. 西瓜书+实战+吴恩达机器学习(三)机器学习基础(多分类、类别不平衡)
  10. P3007 [USACO11JAN]大陆议会The Continental Cowngress(2-SAT)