[MySQL 源码] innodb如何创建二级索引

以下为分析问题时的随笔。写的很凌乱,仅做记录,以备后用。。。。。。

//////////////////////////////////////////////////////////////

ha_innobase::add_index是innodb创建索引的接口函数。

以下所有的讨论都是基于创建一个非聚集的二级索引。因此一些过程是被省略掉了。

1.获取数据词典信息

          indexed_table = dict_table_get(prebuilt->table->name, FALSE);

2.检查索引键是否可用

       error = innobase_check_index_keys(key_info, num_of_keys, prebuilt->table);

3.检查索引列长度

4.

a.创建一个trx对象用于操作innodb数据词典,并创建新的数据词典信息

如果是主键,加LOCK_X,否则加LOCK_S锁

b.加数据词典锁row_mysql_lock_data_dictionary(trx);

c.在ibdata的SYS_INDEXES中加载新的数据词典信息

d.trx_commit_for_mysql(trx); 提交刚刚创建的trx

e.row_mysql_unlock_data_dictionary(trx)

以上步骤完成了对ibdata数据词典内的更新,在 完成后释放锁,这时候,如果在后续的row_merge_build_indexes时crash掉。trx_rollback_active不会drop掉新索引。

5.

调用函数row_merge_build_indexes实际创建索引,我们的讨论主要集中于此。

row_merge_build_indexes会读取表的聚集索引记录,创建临时表来保存这些记录,并使用合并排序算法进行排序以创建索引

a.

首先初始化merge file相关的数据结构,并初始化

merge_files = mem_alloc(n_indexes * sizeof *merge_files);

block_size = 3 * sizeof *block;

block = os_mem_alloc_large(&block_size);

merge_files用于管理针对每个索引创建的临时文件。

block类型为row_merge_block_t,其定义如下:

typedef byte row_merge_block_t[1048576];

因此block_size的值为3* 1048576=3145728字节

b.

创建临时文件

调用row_merge_file_create函数来对该数据的每个成员初始化临时文件。

单独建立一个临时文件tmpfd = row_merge_file_create_low();

c.

调用函数row_merge_read_clustered_index,读取聚集索引记录

一次scan 聚集索引,但为每一个要创建的索引创建entry,并将其加入到每个索引的sort buffer中(row_merge_buf_add)。

当buffer中的记录足够多时,就调用row_merge_buf_sort进行排序,并写入磁盘(row_merge_buf_write &&row_merge_write).

每个buffer的最大tuple数为:

max_tuples = sizeof(row_merge_block_t)/ ut_max(1, dict_index_get_min_size(index));

d.

现在我们可以对上一步准备好的临时文件或buffer进行排序。

排序函数为:

error = row_merge_sort(trx, indexes[i], &merge_files[i],

       block, &tmpfd, table);

在row_merge_sort函数中,对刚刚产生的临时文件进行归并排序(row_merge)。

在5.5的MySQL中,这里存在一个Bug,归并排序存在问题(参阅MySQL官方 bug#54330上Jimmy yang的解释)

尽管Buglist中标注为已经fix,但事实上因为某些意外并没有merge到主干。Percona已经修复了这个问题(https://code.launchpad.net/~laurynas-biveinis/percona-server/bug54330/+merge/94510

e.

排序完成后,调用row_merge_insert_index_tuples插入索引数据

f.

清理工作,及更新统计信息(如果开启了expand_fast_index_creation)

 

 

时间: 2024-09-28 09:32:37

[MySQL 源码] innodb如何创建二级索引的相关文章

[MySQL 源码] Innodb Pessimistic Insert流程

简单跟了下插入导致索引分裂的流程 ////////////////////////////////// 入口函数:row_ins_index_entry 实际上悲观插入和乐观插入是根据row_ins_index_entry_low的第一个参数来判断的 调用两次row_ins_index_entry_low 第一次参数为BTR_MODIFY_LEAF,表示只修改叶子节点,如果失败了 第二次参数为BTR_MODIFY_TREE,表示需要修改B-TREE,这时候会选择调用函数: btr_cur_pes

[MySQL源码] Innodb如何处理auto_inc值

------------------– ha_innobase::write_row是向innodb写入记录的函数,进入函数时自增列的值还没被设置(如何是NULL的话),会调用handler::update_auto_increment来获取并更新自增列,然后再调用row_insert_for_mysql来实际插入记录.我们的精力主要集中在update_auto_increment及其调用的函数上. 先了解下handler的几个跟自增列相关的成员变量(根据注释及gdb推测):  a. ulong

MySQL源码:索引相关的数据结构(前篇)

1. MySQL如何描述某个数据表的索引 MySQL使用TABLE对象来描述一个数据表,那么数据表的索引是如何描述,索引的统计信息又是如何存储的呢? 例如我们有如下数据表: CREATE TABLE `users` ( `id` int(11) NOT NULL, `nick` varchar(32) DEFAULT NULL, `reg_date` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `IND_NICK` (`nick`), KEY `

MySQL源码:Range优化相关的数据结构

1. 背景知识 在开始介绍Range的主要数据结构之前,我们先看Range优化的一些概念和背景.依旧建议先阅读参考文件的[1-8],Sergey Petrunya写的PPT和文档质量都很高,很多图示,非常直观的展示了原理. (1) 什么是Range条件? 参考Range Optimization@MySQL Manual 单列Range和多列Range (2) 给定一个KEY(key1)对应的WHERE条件,如何将其转化成一个Range,下面是"简述",详细参考单列Range: SEL

Linux下MySQL源码编译安装(eg:mysql-5.6.27.tar.gz )

Linux下MySQL源码安装(eg:mysql-5.6.27.tar.gz ): 1:准备MySQL源码安装包: mysql-5.6.27.tar.gz.cmake-3.3.2.tar.gz.ncurses-6.0.tar.gz 注:centos请安装: yum install -y ncurses-devel yum install -y perl-Module-Install.noarch 网址: https://cmake.org/download/ ftp://invisible-is

在eclipse中配置MySQL源码环境(r12笔记第14天)

今天费了些周折,总算搭建好了MySQL源码的调试环境,主要的目的就是想在看代码的时候有一些头绪,让这些开发技巧派上用场.不至于盲人摸象一般的拿着命令肉眼扫视,当然对于代码至于能不能啃下来,那是另外一回事了. 我来说说我的情况,Java开发还有一点基础,所以以前的eclipse还算用得比较熟悉.大家知道InnoDB的源码是c,MySQL Server的是c++,这样一套环境想调试好,如果没有这方面的平台开发经验其实还是有一点难度的.最后我还是决定使用eclipse来做,基于Windows平台. 里

mysql源码安装

我准备学下mysql的源码,所以编译和调试源码是很重要的一部分. 好了废话不多说. 我的环境是 CentOS-6.9-x86_64-minimal,这个可以在阿里的源中直接下.阿里云CentOS6.9下载地址 然后是安装之前的准备工作 先装好环境 yum update yum -y install cmake yum -y install bison yum -y install library* yum -y install libncurses5-dev yum -y install g++

Linux CentOS6.6系统中安装mysql源码包的方法_Linux

这里以CentOS6.6系统中安装MySQL的源码包,进行讲解. 1. mysql源码包的下载 mysql安装包的官方下载地址为:http://dev.mysql.com/downloads/mysql/5.6.html 打开该下载地址后,在 "Select Version:"处,选择要下载的mysql的版本,我选择的是5.6.34:在"Select Platform:"处,选择适用的操作系统类型,由于是下载源码包,故这里我们要选择Source Code. 之后,会

Linux下mysql源码安装笔记_Mysql

1.假设已经有mysql-5.5.10.tar.gz以及cmake-2.8.4.tar.gz两个源文件 (1)先安装cmake(mysql5.5以后是通过cmake来编译的) [root@ rhel5 local]#tar -zxv -f cmake-2.8.4.tar.gz [root@ rhel5 local]#cd cmake-2.8.4 [root@ rhel5 cmake-2.8.4]#./configure [root@ rhel5 cmake-2.8.4]#make [root@