testing-04

Source Code

  • 前篇介绍了MySQL存储索引信息的基本数据结构。本篇将延续下去,介绍MySQL如何找到可以使用的索引,以及期间需要使用的主要数据结构。

    谁适合阅读: 本文不打算从High Level来介绍MySQL索引及其使用,相反是从MySQL源码对应的数据结构开始介绍。如果你了解MySQL索引的基本原理,还打算继续从源码的角度解决一些索引使用的问题,那么你适合参考本文,否则,打住,真的很枯燥:(。在可见的未来,作者还将介绍Range优化相关的数据结构等。

    0. 概述

    本文介绍MySQL如何发现WHERE条件中的等值表达式,并通过分析这些等值表达式,找到可以使用的索引。在这个过程中,MySQL将递归的访问所有WHERE条件”谓词”,并将等值表达式都存储到KEY_FIELD对象的数组中。

    然后遍历该KEY_FIELD数组,并同时对比所有索引列,找到哪些字段是在索引列中出现,这些字段则可能可以使用索引,MySQL将所有这些字段都存储在对象KEYUSE数组中。

    最后,对KEYUSE进行处理,包括排序、删除无法使用的索引列。这时KEYUSE数组就是所有可以使用REF的索引列了。 (more…)

  • 很枯燥的,配首背景音乐吧:

    本文将尝试介绍MySQL索引存储相关的数据结构。程序=数据结构+算法,了解数据结构,然后就可以进一步了解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 `IND_REGDATE` (`reg_date`) )

    该表有索引,PRIMARY KEY、IND_NICK、IND_REGDATE,我们来看看MySQL内部是如何存储这三个索引,以及如何使用这些索引的统计信息的。下图,描述了存储一个数据表索引的主要结构:

    indexoftable-s (more…)

  • 前篇介绍了MySQL如何从SQL语句转换成一个内部对象。本文是前篇的延续,将更加详细的介绍WHERE语句对应的Item对象。

    1. Item对象@MySQL Internal

    (建议阅读:The Item Class@MySQL Internals Manual,忽略本小结)

    MySQL Internals Manual较为详细的介绍了Item对象。Item对象经常被称作”thingamabob”( A thingamabob is a noun used to describe items that either you can’t remember the name of or that don’t actually exist.)。Item是一个类,每一个Item实例都:(1)代表一个SQL语句里的对象;(2)有取值;(3)有数据类型指针。

    下面列出的的SQL相关的对象都是一个Item对象,或者继承至Item:(1)一段字符; (2)数据表的某列; (3)一个局部或全局变量; (4)一个存储过程的变量; (5) 一个用户参数; (6)一个函数/存储过程(这包括运算符+、||、=、like等) 。例如下面的SQL语句: (more…)

  • 自从有了微薄后博客就写得少了,上一篇博客已经是6月份写的了… 从写第一篇关于MySQL源码的文章之后也已经过了很久,继续上路。

    优化器是关系数据库的一个重要而有特色的部分,优化器的理论和实践也多半也都很复杂,本系列文章希望通过解析MySQL优化器,来用好MySQL,扬其长,避其短。顺便也一窥关系数据库优化器的实现思路。文章将重点介绍重要的数据结构和数据结构之间的关系,而不是侧重于代码(”Bad programmers worry about the code. Good programmers worry about data structures and their relationships.”)。

    0 写在前面

    本文解决了什么问题:希望通过这些文章能够帮你更加顺畅的理解MySQL优化器的行为;在你阅读MySQL源代码之前了解更多的背后思路。

    本文不解决什么问题:教你如何读懂源代码;

    这个系列很长,大概按这样的思路进行下去: 基本的数据结构、语法解析、JOIN的主要算法、JOIN顺序和单表访问。数据结构(以及他们的关系)和算法流程总是相互穿插介绍。

    建议阅读:参考文献中的文章和书籍,都建议在阅读本文之前阅读。

    1 SQL语句解析基础

    1.1 语法解析基础/Flex与Bison

    MySQL语法解析封装在函数MYSQLparser中完成。跟其他的语法解析器一样,它包含两个模块:词法分析(Lexical scanner)和语法规则(Grammar rule module)。词法分析将整个SQL语句打碎成一个个单词(Token),而语法规则模块则根据MySQL定义的语法规则生成对应的数据结构,并存储在对象THD->LEX结构当中。最后优化器,根据这里的数据,生成执行计划,再调用存储引擎接口执行。

    词法分析和语法规则模块有两个较成熟的开源工具Flex和Bison分别用来解决这两个问题。MySQL出于性能和灵活考虑,选择了自己完成词法解析部分,语法规则部分使用Bison。词法解析和Bison沟通的核心函数是由词法解析器提供的函数接口yylex(),在Bison中,必要的时候调用yylex()获得词法解析的数据,完成自己的语法解析。Bison的入口时yyparse(),在MySQL中是,MYSQLParse。

    如果对词法分析和语法规则模块感到陌生,建议阅读参考文献[4][5][6]先注1,否则很难理解整个架构,或者至少会有很强的断层感。而且,根据Bison的Action追踪MySQL数据的存储结构是很有效的。 (more…)

  • 这是该系列的第三篇文章(12)了。之所以选择并发线程控制着手研究InnoDB的代码有两个原因:第一,这段代码相对独立,不要了解太多的相关代码就可以理解;第二,稍微多看一些代码你会发现,到处都是线程并发控制相关的代码出现,所以这也是一个基础。

    第一篇中,介绍了InnoDB内部排他锁的实现,第二篇则介绍InnoDB内部读写锁的实现原理(这里说的“内部”是为了区别于数据库层面的读写锁)。本篇则将延续第二篇,介绍读写锁相关的代码实现。 (more…)

  • 前面做了一个开始,沿着路慢慢走下去。

    0. 起源

    开始之前,这里可以说说这次准备开始研究源代码的一个很大诱因了。前一段时间在生产环境遇到了一个InnoDB报错,这个错误甚至会导致InnoDB Crash:

    InnoDB: Warning: a long semaphore wait:
    –Thread 1222654272 has waited at ./include/btr0btr.ic line 53 for 241.00 seconds the semaphore:
    S-lock on RW-latch at 0x2aaab510b818 created in file buf/buf0buf.c line 680

    沿着这里的线索 buf/buf0buf.c line 680 找到了:

    678 mutex_create(&block->mutex, SYNC_BUF_BLOCK);
    679
    680 rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
    681 ut_ad(rw_lock_validate(&(block->lock)));

    继续,就开始看rw_lock_create的实现,然后感觉需要看更多基础的一点的内容,这样就有了前面一片文章,继续研究,就有了现在的这篇文章。 (more…)