Innodb parent table open时导致crash
case描述:
innodb中,父表和子表通过foreign constraint进行关联, 因为在更新数据时需要check 外键constraint,如果父表被大量的子表reference,
那么在open的时候,需要open所有的child table和所有的foreign constraint,导致时间过长,产生long semaphore wait 。
分析过程:
case 用例:
CREATE TABLE `t1` (
`f1` int() NOT NULL,
PRIMARY KEY (`f1`)
) ENGINE=InnoDB CREATE TABLE `fk_1` (
`f1` int() NOT NULL,
PRIMARY KEY (`f1`),
CONSTRAINT `pc1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB
...... 这里建了fk_[-]张表。
1. 背景:innodb数据字典
innodb使用系统表空间保存表相关的数据字典,系统的数据字典包括:
- SYS_TABLES
- SYS_INDEXES
- SYS_COLUMNS
- SYS_FIELDS
- SYS_FOREIGN
- SYS_FOREIGN_COLS
- SYS_STATS
在load某个表的时候,分别从这些表中把表相关的index,column, index_field, foreign, foreign_col数据保存到dictionary cache中。
对应的内存对象分别是:dict_col_struct,dict_field_struct,dict_index_struct,dict_table_struct,dict_foreign_struct。
这些对象全局唯一,在dictionary cache只保留一份,并使用dict_sys->mutex进行同步保护,所有open的handler引用到这些对象上。
注意:系统的数据字典同样是innodb的聚簇索引表,并受redo保护。
2. open过程
入口函数ha_innobase::open()
dict_load_table:
1. 通过sys_tables系统表,load table相关的定义
2. 通过sys_indexes系统表,根据table_id load 所有相关index
3. 通过sys_columns系统表,根据table_id load 所有的columns
4. 通过sys_fields系统表,根据index_id load 所有index的field
5. 通过sys_foreign系统表,load所有关联的表和foreign key
在load这些定义的时候,过程都是:
1. 通过某个字段,查找系统字典表
2. 根据查询的记录建立内存对象,并加入到全局cache中
但在load foreign的时候,会有一些不同,因为foreign key于两张表相关联。下面详细介绍下load foreign的过程。
3. load foreign的详细过程
如下图所示foreign的关联关系:

load的步骤:
3.1: 根据表名t1 查找sys_foreign. 而sys_foreign表上一共有三个索引:
index_1(id): cluster_index
index_2(for_name): secondary_index
index_3(ref_name): secondary_index
所以,根据for_name='t1', ref_name='t1'检索出来所有相关的foreign_id.
3.2: 根据3.1检索出来的foreign_id, load foreign对象,并打开相关fk_[1-10000]表。
3.3: 加入cache
因为没有专门的cache,foreign分别加入到for_name->foreign_list, ref_name->refence_list
问题的关键:因为foreign是全局唯一的,但foreign又与两个表关联,所以,有可能在open 其它表的时候
已经打开过,所以,create foreign对象后,需要判断以下四个list,是否已经存在,如果存在就直接使用。
dict_foreign_find:分别查询这四个list,如果已经存在,则free新建的foreign对象,引用已经存在的。
for_name->foreign_list
for_name->refence_list
ref_name->foreign_list
ref_name->refence_list
如果不存在,把新建的foreign加入到for_name->foreign_list,ref_name->refence_list链表中。
4. 问题的原因:
因为第一次load,所以find都没有找到,但这四个都是list,随着open的越来越多,检索的代价越来越大。
而整个过程中,都一直持有trx_sys->mutex,最终导致了long semaphore wait。
5. 问题改进方法:
在MySQL 5.5.39版本中,进行了修复,修复的方法就是,除了foreign_list,referenced_list。
另外又增加了两个red_black tree,如下源码所示:
struct dict_table_struct{
table_id_t id; /*!< id of the table */
mem_heap_t* heap; /*!< memory heap */
char* name; /*!< table name */
UT_LIST_BASE_NODE_T(dict_foreign_t)
foreign_list; /*!< list of foreign key constraints in the table; these refer to columns in other tables */
UT_LIST_BASE_NODE_T(dict_foreign_t)
referenced_list;/*!< list of foreign key constraints which refer to this table */
ib_rbt_t* foreign_rbt; /*!< a rb-tree of all foreign keys listed in foreign_list, sorted by foreign->id */
ib_rbt_t* referenced_rbt; /*!< a rb-tree of all foreign keys listed in referenced_list, sorted by foreign->id */
在初始化list的时候,初始化一份red_black tree. 在dict_foreign_find的过程中,直接查找rbt,这样查询的代价大大降低。
Innodb parent table open时导致crash的更多相关文章
- IE6 IE7: div中table宽度100%导致的宽度问题
问题现象:定义了DOCTYPE的页面 当表格的内容比div的高度还要高时,div会出现滚动条,同时在IE6和IE7下会出现问题: IE6:此时table的100%宽度还是没有滚动条那是的宽度,出现滚动 ...
- MySQL 5.6 解决InnoDB: Error: Table "mysql"."innodb_table_stats" not found.问题
在安装MySQL 5.6.30时,安装完成后,后台日志报如下警告信息:2016-05-27 12:25:27 7fabf86f7700 InnoDB: Error: Table "mysql ...
- 还原堆栈信息,分析地形系统使用ASTC格式的纹理导致Crash的问题
0x00 前言 在这篇文章中,我们选择了过去一周Unity官方社区交流群中比较有代表性的几个问题,总结在这里和大家进行分享.主要涵盖了IL2CPP.Scripting.Virtual Reality. ...
- 【MySQL】5.6.x InnoDB Error Table mysql.innodb_table_stats not found
[问题描述]: 检查error log的时候发现大量warnings: [Warning] InnoDB Error Table mysql.innodb_index_stats not found ...
- InnoDB: Error: Table "mysql"."innodb_table_stats" not found.
1,Mysqldump的时候报错例如以下: 2014-05-05 14:12:37 7f004a9a2700 InnoDB: Error: Table "mysql"." ...
- 使用vxe table组件时,edit-render配置$select',选中option后关闭cell的激活状态,显示选中option的value问题
在我的项目中使用vxe table组件时,edit-render配置{name: '$select', options: [{label:"脉搏",value:"maib ...
- [转]File Descriptor泄漏导致Crash: Too many open files
在实际的Android开发过程中,我们遇到了一些奇奇怪怪的Crash,通过sigaction再配合libcorkscrew以及一些第三方的Crash Reporter都捕获不到发生Crash的具体信息 ...
- @PathVariable出现点号"."时导致路径参数截断获取不全的解决办法
@PathVariable出现点号"."时导致路径参数截断获取不全的解决办法 比如,我路径是/test/{name},name的值是1.2.3.4,后台用@PathVariable ...
- iOS -- xxxViewController进行pop时直接crash进main.m,EXC_BAD_ACCESS(code=1,address=0x20)
今天在调试程序时,遇到了奇怪的错误.我从主页跳进(push)一个ViewController时一切正常,但是返回主页(pop)时却crash了,直接跳进了main.m(EXC_BAD_ACCESS(c ...
随机推荐
- javassist动态修改class
import java.io.IOException;import java.io.PrintWriter; import javassist.CannotCompileException;impor ...
- php 字母大小写转换的函数
分享下,在php编程中,将字母大小写进行转换的常用函数. 1.将字符串转换成小写strtolower(): 该函数将传入的字符串参数所有的字符都转换成小写,并以小定形式放回这个字符串 2.将字符转成大 ...
- max_size, capacity and size 的区别
The max_size() function returns the maximum number of elements that the container can hold. The max_ ...
- SQL动态更新表字段 传入字段可能为空
小技巧: 项目组有修改产品的基本信息字段 但有时候传入的字段可能为空 也可能不为空 动态修改表中字段. USE [BetaProductMarket_DB] GO )) BEGIN DROP PRO ...
- 1079. Total Sales of Supply Chain (25)
时间限制 250 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue A supply chain is a network of r ...
- 十、mysql事务的简介
1. myisam跟memory支持表级别锁定 BDB 页级锁定 Innodb 行级锁定 2.表锁(不是表嫂哈) lock table read //只读表锁,也就是说执行了这个锁后,锁内的操作只能为 ...
- C#中用ILMerge将所有引用的DLL打成一个DLL文件
有些文件是必须一起使用的,如果能把多个DLL打包成一个DLL文件,那么引用文件的时候就不需要一个个地去引用,而且每次移动文件的时候也不至于少了哪个必须的DLL文件. 多个DLL文件打包成一个DLL文件 ...
- 微软Hololens设备 浅分析
微软Hololens的定位是一款MR 设备(Mixed reality).MR与AR的不同我认为是MR能够将真实环境的场景信息与虚拟对象进行完美的融合,它是基于SLAM(SimultaneousLoc ...
- json分别算出元素的个数和最多的元素
个数: var str = 'aaafsdsaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!js ...
- [Unity3D]支持的视频格式
Unity3d只支持 .mov, .mpg, .mpeg, .mp4, .avi, .asf这些格式.