学习

第6章_快速查询的秘籍-B+树索引

第6章 快速查询的秘籍-B+树索引

前面我们详细介绍了InnoDB数据页的7个组成部分,知道了各个数据页可以组成一个双向链表,而每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表,每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录(如果你对这段话有一丁点儿疑惑,那么接下来的部分不适合你,返回去看一下数据页结构吧)。页和记录的关系示意图如下:

其中页a、页b、页c … 页n 这些页可以不在物理结构上相连,只要通过双向链表相关联即可。

没有索引的查找 #

本集的主题是索引,在正式介绍索引之前,我们需要了解一下没有索引的时候是怎么查找记录的。为了方便大家理解,我们下面先只介绍搜索条件为对某个列精确匹配的情况,所谓精确匹配,就是搜索条件中用等于=连接起的表达式,比如这样: SELECT [列名列表] FROM 表名 WHERE 列名 = xxx;

在一个页中的查找 #

假设目前表中的记录比较少,所有的记录都可以被存放到一个页中,在查找记录的时候可以根据搜索条件的不同分为两种情况:

以主键为搜索条件

这个查找过程我们已经很熟悉了,可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录。

以其他列作为搜索条件

对非主键列的查找的过程可就不这么幸运了,因为在数据页中并没有对非主键列建立所谓的页目录,所以我们无法通过二分法快速定位相应的。这种情况下只能从最小记录开始依次遍历单链表中的每条记录,然后对比每条记录是不是符合搜索条件。很显然,这种查找的效率是非常低的。

在很多页中查找 #

大部分情况下我们表中存放的记录都是非常多的,需要好多的数据页来存储这些记录。在很多页中查找记录的话可以分为两个步骤:

  1. 定位到记录所在的页。
  2. 从所在的页内中查找相应的记录。

在没有索引的情况下,不论是根据主键列或者其他列的值进行查找,由于我们并不能快速的定位到记录所在的页,所以只能从第一个页沿着双向链表一直往下找,在每一个页中根据我们刚刚介绍过的查找方式去查找指定的记录。因为要遍历所有的数据页,所以这种方式显然是超级耗时的,如果一个表有一亿条记录,使用这种方式去查找记录那要等到猴年马月才能等到查找结果。所以祖国和人民都在期盼一种能高效完成搜索的方法,索引同志就要亮相登台了。

索引 #

为了故事的顺利发展,我们先建一个表: mysql> CREATE TABLE index_demo( -> c1 INT, -> c2 INT, -> c3 CHAR(1), -> PRIMARY KEY(c1) -> ) ROW_FORMAT = Compact; Query OK, 0 rows affected (0.03 sec) 这个新建的index_demo表中有2个INT类型的列,1个CHAR(1)类型的列,而且我们规定了c1列为主键,这个表使用Compact行格式来实际存储记录的。为了我们理解上的方便,我们简化了一下index_demo表的行格式示意图:

...

第5章 盛放记录的大盒子-InnoDB数据页结构

第5章 盛放记录的大盒子-InnoDB数据页结构

不同类型的页简介 #

前面我们简单提了一下的概念,它是InnoDB管理存储空间的基本单位,一个页的大小一般是16KBInnoDB为了不同的目的而设计了许多种不同类型的,比如存放表空间头部信息的页,存放Insert Buffer信息的页,存放INODE信息的页,存放undo日志信息的页等等等等。当然了,如果我说的这些名词你一个都没有听过,就当我放了个屁吧~ 不过这没有一毛钱关系,我们今儿个也不准备说这些类型的页,我们聚焦的是那些存放我们表中记录的那种类型的页,官方称这种存放记录的页为索引(INDEX)页,鉴于我们还没有了解过索引是个什么东西,而这些表中的记录就是我们日常口中所称的数据,所以目前还是叫这种存放记录的页为数据页吧。

数据页结构的快速浏览 #

数据页代表的这块16KB大小的存储空间可以被划分为多个部分,不同部分有不同的功能,各个部分如图所示:

从图中可以看出,一个InnoDB数据页的存储空间大致被划分成了7个部分,有的部分占用的字节数是确定的,有的部分占用的字节数是不确定的。下面我们用表格的方式来大致描述一下这7个部分都存储一些什么内容(快速的瞅一眼就行了,后边会详细介绍的): 名称 中文名 占用空间大小 简单描述 File Header 文件头部 38字节 页的一些通用信息 Page Header 页面头部 56字节 数据页专有的一些信息 Infimum + Supremum 最小记录和最大记录 26字节 两个虚拟的行记录 User Records 用户记录 不确定 实际存储的行记录内容 Free Space 空闲空间 不确定 页中尚未使用的空间 Page Directory 页面目录 不确定 页中的某些记录的相对位置 File Trailer 文件尾部 8字节 校验页是否完整
小贴士:我们接下来并不打算按照页中各个部分的出现顺序来依次介绍它们,因为各个部分中会出现很多大家目前不理解的概念,这会打击各位读文章的信心与兴趣,希望各位能接受这种拍摄手法~

记录在页中的存储 #

在页的7个组成部分中,我们自己存储的记录会按照我们指定的行格式存储到User Records部分。但是在一开始生成页的时候,其实并没有User Records这个部分,每当我们插入一条记录,都会从Free Space部分,也就是尚未使用的存储空间中申请一个记录大小的空间划分到User Records部分,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使用完了,如果还有新的记录插入的话,就需要去申请新的页了,这个过程的图示如下:

为了更好的管理在User Records中的这些记录,InnoDB可费了一番力气呢,在哪费力气了呢?不就是把记录按照指定的行格式一条一条摆在User Records部分么?其实这话还得从记录行格式的记录头信息中说起。

...

第4章_从一条记录说起-InnoDB记录结构

第4章 从一条记录说起-InnoDB记录结构

准备工作 #

到现在为止,MySQL对于我们来说还是一个黑盒,我们只负责使用客户端发送请求并等待服务器返回结果,表中的数据到底存到了哪里?以什么格式存放的?MySQL是以什么方式来访问的这些数据?这些问题我们统统不知道,对于未知领域的探索向来就是社会主义核心价值观中的一部分,作为新一代社会主义接班人,不把它们搞懂怎么支援祖国建设呢?

我们前面介绍请求处理过程的时候提到过,MySQL服务器上负责对表中数据的读取和写入工作的部分是存储引擎,而服务器又支持不同类型的存储引擎,比如InnoDBMyISAMMemory什么的,不同的存储引擎一般是由不同的人为实现不同的特性而开发的,真实数据在不同存储引擎中存放的格式一般是不同的,甚至有的存储引擎比如Memory都不用磁盘来存储数据,也就是说关闭服务器后表中的数据就消失了。由于InnoDBMySQL默认的存储引擎,也是我们最常用到的存储引擎,我们也没有那么多时间去把各个存储引擎的内部实现都看一遍,所以本集要介绍的是使用InnoDB作为存储引擎的数据存储结构,了解了一个存储引擎的数据存储结构之后,其他的存储引擎都是依葫芦画瓢,等我们用到了再说。

InnoDB页简介 #

InnoDB是一个将表中的数据存储到磁盘上的存储引擎,所以即使关机后重启我们的数据还是存在的。而真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中,如果是处理写入或修改请求的话,还需要把内存中的内容刷新到磁盘上。而我们知道读写磁盘的速度非常慢,和内存读写差了几个数量级,所以当我们想从表中获取某些记录时,InnoDB存储引擎需要一条一条的把记录从磁盘上读出来么?不,那样会慢死,InnoDB采取的方式是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中。

InnoDB行格式 #

我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为行格式或者记录格式。设计InnoDB存储引擎的大佬们到现在为止设计了4种不同类型的行格式,分别是CompactRedundantDynamicCompressed行格式,随着时间的推移,他们可能会设计出更多的行格式,但是不管怎么变,在原理上大体都是相同的。

指定行格式的语法 #

我们可以在创建或修改表的语句中指定行格式: ``` CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称

ALTER TABLE 表名 ROW_FORMAT=行格式名称 比如我们在xiaohaizi数据库里创建一个演示用的表record_format_demo,可以这样指定它的行格式 mysql> USE xiaohaizi; Database changed

mysql> CREATE TABLE record_format_demo ( -> c1 VARCHAR 10),>c2VARCHAR(10)NOTNULL,>c3CHAR(10),>c4VARCHAR(10)>10), -> c2 VARCHAR(10) NOT NULL, -> c3 CHAR(10), -> c4 VARCHAR(10) -> CHARSET=ascii ROW_FORMAT=COMPACT; Query OK, 0 rows affected (0.03 sec) 可以看到我们刚刚创建的这个表的行格式就是Compact,另外,我们还显式指定了这个表的字符集为ascii,因为ascii字符集只包括空格、标点符号、数字、大小写字母和一些不可见字符,所以我们的汉字是不能存到这个表里的。我们现在向这个表中插入两条记录: mysql> INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES(‘aaaa’, ‘bbb’, ‘cc’, ’d’), (’eeee’, ‘fff’, NULL, NULL); Query OK, 2 rows affected (0.02 sec) Records: 2 Duplicates: 0 Warnings: 0 现在表中的记录就是这个样子的: mysql> SELECT * FROM record_format_demo; +——+—–+——+——+ | c1 | c2 | c3 | c4 | +——+—–+——+——+ | aaaa | bbb | cc | d | | eeee | fff | NULL | NULL | +——+—–+——+——+ 2 rows in set (0.00 sec)

...

第3章_乱码的前世今生-字符集和比较规则

第3章 乱码的前世今生-字符集和比较规则

字符集和比较规则简介 #

字符集简介 #

我们知道在计算机中只能存储二进制数据,那该怎么存储字符串呢?当然是建立字符与二进制数据的映射关系了,建立这个关系最起码要搞清楚两件事儿:

  1. 你要把哪些字符映射成二进制数据? 也就是界定清楚字符范围。
  2. 怎么映射? 将一个字符映射成一个二进制数据的过程也叫做编码,将一个二进制数据映射到一个字符的过程叫做解码

人们抽象出一个字符集的概念来描述某个字符范围的编码规则。比方说我们来自定义一个名称为xiaohaizi的字符集,它包含的字符范围和编码规则如下:

包含字符'a''b''A''B'

编码规则如下:

采用1个字节编码一个字符的形式,字符和字节的映射关系如下: 'a' -> 00000001 (十六进制:0x01) 'b' -> 00000010 (十六进制:0x02) 'A' -> 00000011 (十六进制:0x03) 'B' -> 00000100 (十六进制:0x04)

有了xiaohaizi字符集,我们就可以用二进制形式表示一些字符串了,下面是一些字符串用xiaohaizi字符集编码后的二进制表示: 'bA' -> 0000001000000011 (十六进制:0x0203) 'baB' -> 000000100000000100000100 (十六进制:0x020104) 'cd' -> 无法表示,字符集xiaohaizi不包含字符'c'和'd'

比较规则简介 #

在我们确定了xiaohaizi字符集表示字符的范围以及编码规则后,怎么比较两个字符的大小呢?最容易想到的就是直接比较这两个字符对应的二进制编码的大小,比方说字符'a'的编码为0x01,字符'b'的编码为0x02,所以'a'小于'b',这种简单的比较规则也可以被称为二进制比较规则,英文名为binary collation

二进制比较规则是简单,但有时候并不符合现实需求,比如在很多场合对于英文字符我们都是不区分大小写的,也就是说'a''A'是相等的,在这种场合下就不能简单粗暴的使用二进制比较规则了,这时候我们可以这样指定比较规则:

  1. 将两个大小写不同的字符全都转为大写或者小写。
  2. 再比较这两个字符对应的二进制数据。

这是一种稍微复杂一点点的比较规则,但是实际生活中的字符不止英文字符一种,比如我们的汉字有几万之多,对于某一种字符集来说,比较两个字符大小的规则可以制定出很多种,也就是说同一种字符集可以有多种比较规则,我们稍后就要介绍各种现实生活中用的字符集以及它们的一些比较规则。

一些重要的字符集 #

不幸的是,这个世界太大了,不同的人制定出了好多种字符集,它们表示的字符范围和用到的编码规则可能都不一样。我们看一下一些常用字符集的情况:

ASCII字符集

共收录128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符。由于总共才128个字符,所以可以使用1个字节来进行编码,我们看一些字符的编码方式: 'L' -> 01001100(十六进制:0x4C,十进制:76) 'M' -> 01001101(十六进制:0x4D,十进制:77)

ISO 8859-1字符集

...

第2章_MySQL的调控按钮-启动选项和系统变量

第2章 MySQL的调控按钮-启动选项和系统变量

如果你用过手机,你的手机上一定有一个设置的功能,你可以选择设置手机的来电铃声、设置音量大小、设置解锁密码等等。假如没有这些设置功能,我们的生活将置于尴尬的境地,比如在图书馆里无法把手机设置为静音,无法把流量开关关掉以节省流量,在别人得知解锁密码后无法更改密码~ MySQL的服务器程序和客户端程序也有很多设置项,比如对于MySQL服务器程序,我们可以指定诸如允许同时连入的客户端数量、客户端和服务器通信方式、表的默认存储引擎、查询缓存的大小等设置项。对于MySQL客户端程序,我们之前已经见识过了,可以指定需要连接的服务器程序所在主机的主机名或IP地址、用户名及密码等信息。

这些设置项一般都有各自的默认值,比方说服务器允许同时连入的客户端的默认数量是151,表的默认存储引擎是InnoDB,我们可以在程序启动的时候去修改这些默认值,对于这种在程序启动时指定的设置项也称之为启动选项(startup options),这些选项控制着程序启动后的行为。在MySQL安装目录下的bin目录中的各种可执行文件,不论是服务器相关的程序(比如mysqldmysqld_safe)还是客户端相关的程序(比如mysqlmysqladmin),在启动的时候基本都可以指定启动参数。这些启动参数可以放在命令行中指定,也可以把它们放在配置文件中指定。下面我们以mysqld为例,来详细介绍指定启动选项的格式。需要注意的一点是,我们现在要介绍的是设置启动选项的方式,下面出现的启动选项不论大家认不认识,先不用去纠结每个选项具体的作用是什么,之后我们会对一些重要的启动选项详细介绍。

在命令行上使用选项 #

如果我们在启动客户端程序时在-h参数后边紧跟服务器的IP地址,这就意味着客户端和服务器之间需要通过TCP/IP网络进行通信。因为我的客户端程序和服务器程序都装在一台计算机上,所以在使用客户端程序连接服务器程序时指定的主机名是127.0.0.1的情况下,客户端进程和服务器进程之间会使用TCP/IP网络进行通信。如果我们在启动服务器程序的时候就禁止各客户端使用TCP/IP网络进行通信,可以在启动服务器程序的命令行里添加skip-networking启动选项,就像这样: mysqld --skip-networking 可以看到,我们在命令行中指定启动选项时需要在选项名前加上--前缀。另外,如果选项名是由多个单词构成的,它们之间可以由短划线-连接起来,也可以使用下划线_连接起来,也就是说skip-networkingskip_networking表示的含义是相同的。所以上面的写法与下面的写法是等价的: mysqld --skip_networking 在按照上述命令启动服务器程序后,如果我们再使用mysql来启动客户端程序时,再把服务器主机名指定为127.0.0.1(IP地址的形式)的话会显示连接失败: ``` mysql -h127.0.0.1 -uroot -p Enter password:

ERROR 2003 (HY000): Can’t connect to MySQL server on ‘127.0.0.1’ (61) ``` 这就意味着我们指定的启动选项skip-networking生效了!

再举一个例子,我们前面说过如果在创建表的语句中没有显式指定表的存储引擎的话,那就会默认使用InnoDB作为表的存储引擎。如果我们想改变表的默认存储引擎的话,可以这样写启动服务器的命令行: mysqld --default-storage-engine=MyISAM 我们现在就已经把表的默认存储引擎改为MyISAM了,在客户端程序连接到服务器程序后试着创建一个表: mysql> CREATE TABLE sys_var_demo( -> i INT -> ); Query OK, 0 rows affected (0.02 sec) 这个定义语句中我们并没有明确指定表的存储引擎,创建成功后再看一下这个表的结构: mysql> SHOW CREATE TABLE sys_var_demo\G *************************** 1. row *************************** Table: sys_var_demo Create Table: CREATE TABLE sys_var_demo(i int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 1 row in set (0.01 sec) 可以看到该表的存储引擎已经是MyISAM了,说明启动选项default-storage-engine生效了。

...

第1章_装作自己是个小白-重新认识MySQL

第1章 装作自己是个小白-重新认识MySQL

MySQL的客户端/服务器架构 #

以我们平时使用的微信为例,它其实是由两部分组成的,一部分是客户端程序,一部分是服务器程序。客户端可能有很多种形式,比如手机APP,电脑软件或者是网页版微信,每个客户端都有一个唯一的用户名,就是你的微信号,另一方面,腾讯公司在他们的机房里运行着一个服务器软件,我们平时操作微信其实都是用客户端来和这个服务器来打交道。比如狗哥用微信给猫爷发了一条消息的过程其实是这样的:

  1. 消息被客户端包装了一下,添加了发送者和接收者信息,然后从狗哥的微信客户端传送给微信服务器;
  2. 微信服务器从消息里获取到它的发送者和接收者,根据消息的接收者信息把这条消息送达到猫爷的微信客户端,猫爷的微信客户端里就显示出狗哥给他发了一条消息。

MySQL的使用过程跟这个是一样的,它的服务器程序直接和我们存储的数据打交道,然后可以有好多客户端程序连接到这个服务器程序,发送增删改查的请求,然后服务器就响应这些请求,从而操作它维护的数据。和微信一样,MySQL的每个客户端都需要提供用户名密码才能登录,登录之后才能给服务器发请求来操作某些数据。我们日常使用MySQL的情景一般是这样的:

  1. 启动MySQL服务器程序。
  2. 启动MySQL客户端程序并连接到服务器程序。
  3. 在客户端程序中输入一些命令语句作为请求发送到服务器程序,服务器程序收到这些请求后,会根据请求的内容来操作具体的数据并向客户端返回操作结果。

我们知道计算机很牛逼,在一台计算机上可以同时运行多个程序,比如微信、QQ、音乐播放器、文本编辑器等,每一个运行着的程序也被称为一个进程。我们的MySQL服务器程序和客户端程序本质上都算是计算机上的一个进程,这个代表着MySQL服务器程序的进程也被称为MySQL数据库实例,简称数据库实例

每个进程都有一个唯一的编号,称为进程ID,英文名叫PID,这个编号是在我们启动程序的时候由操作系统随机分配的,操作系统会保证在某一时刻同一台机器上的进程号不重复。比如你打开了计算机中的QQ程序,那么操作系统会为它分配一个唯一的进程号,如果你把这个程序关掉了,那操作系统就会把这个进程号回收,之后可能会重新分配给别的进程。当我们下一次再启动 QQ程序的时候分配的就可能是另一个编号。每个进程都有一个名称,这个名称是编写程序的人自己定义的,比如我们启动的MySQL服务器进程的默认名称为mysqld, 而我们常用的MySQL客户端进程的默认名称为mysql

MySQL的安装 #

不论我们通过下载源代码自行编译安装的方式,还是直接使用官方提供的安装包进行安装之后,MySQL的服务器程序和客户端程序都会被安装到我们的机器上。不论使用上述两者的哪种安装方式,一定一定一定(重要的话说三遍)要记住你把MySQL安装到哪了,换句话说,一定要记住MySQL的安装目录。 小贴士:MySQL的大部分安装包都包含了服务器程序和客户端程序,不过在Linux下使用RPM包时会有单独的服务器RPM包和客户端RPM包,需要分别安装。

另外,MySQL可以运行在各种各样的操作系统上,我们后边会讨论在类UNIX操作系统和Windows操作系统上使用的一些差别。为了方便大家理解,我在macOS 操作系统(苹果电脑使用的操作系统)和Windows操作系统上都安装了MySQL,它们的安装目录分别是:

macOS操作系统上的安装目录: /usr/local/mysql/

Windows操作系统上的安装目录: C:\Program Files\MySQL\MySQL Server 5.7

下面我会以这两个安装目录为例来进一步扯出更多的概念,不过一定要注意,这两个安装目录是我的运行不同操作系统的机器上的安装目录,一定要记着把下面示例中用到安装目录的地方替换为你自己机器上的安装目录小贴士:类UNIX操作系统非常多,比如FreeBSD、Linux、macOS、Solaris等都属于UNIX操作系统的范畴,我们这里使用macOS操作系统代表类UNIX操作系统来运行MySQL。

bin目录下的可执行文件 #

MySQL的安装目录下有一个特别特别重要的bin目录,这个目录下存放着许多可执行文件,以macOS系统为例,这个bin目录的绝对路径就是(在我的机器上): /usr/local/mysql/bin 我们列出一些在macOS中这个bin目录下的一部分可执行文件来看一下(文件太多,全列出来会刷屏的): . ├── mysql ├── mysql.server -> ../support-files/mysql.server ├── mysqladmin ├── mysqlbinlog ├── mysqlcheck ├── mysqld ├── mysqld_multi ├── mysqld_safe ├── mysqldump ├── mysqlimport ├── mysqlpump ... (省略其他文件) 0 directories, 40 files Windows中的可执行文件与macOS中的类似,不过都是以.exe为扩展名的。这些可执行文件都是与服务器程序和客户端程序相关的,后边我们会详细介绍一些比较重要的可执行文件,现在先看看执行这些文件的方式。

...

第0章_万里长征第一步(非常重要)-如何愉快的阅读本小册

第0章 万里长征第一步(非常重要)-如何愉快的阅读本小册

购买前警告⚠️ #

  • 此小册并非数据库入门书籍,需要各位知道增删改查是什么意思,并且能用 SQL 语言写出来,当然并不要求各位知道的太多,你甚至可以不知道连接的语法都可以。不过如果你连SELECTINSERT这些单词都没听说过那本小册并不适合你。
  • 此小册非正经科学专著,亦非十二五国家级规划教材,也没有大段代码和详细论证,有的全是图,喜欢正经论述的同学请避免购买本小册。
  • 此小册作者乃一无业游民,非专业大佬,没有任何职称,只是单单喜欢把复杂问题讲清楚的那种快感,所以喜欢作者有 Google、Facebook 高级开发工程师,二百年工作经验等 Title 的同学请谨慎购买。
  • 此小册是用于介绍 MySQL 的工作原理以及对我们程序猿的影响,并不是介绍概念设计、逻辑设计、物理设计、范式化之类的数据库设计方面的知识,希望了解上述这些知识的同学来错地方了。
  • 文章标题中的“从根儿上理解MySQL”**其实是专门雇了 UC 震惊部小编起的,纯属为了吸引大家眼球。严格意义上说,本书只是介绍MySQL内核的一些核心概念的小白进阶书籍。大家读完本小册也不会一下子晋升业界大佬,当上 CTO,迎娶白富美,走上人生巅峰。希望本小册能够帮助大家解决一些工作、面试过程中的问题,逐渐成为一个更好的工程师,有兴趣的小伙伴可以再深入研究一下 MySQL,说不定你就是下一个数据库泰斗啦。

购买并阅读本小册的建议 #

  • 本小册是一本待出版的纸质书籍,并非一些杂碎文章的集合,是非常有结构和套路的,所以大家阅读时千万不能当作厕所蹲坑、吃饭看手机时的所谓碎片化读物。碎片化阅读只适合听听矮大紧、罗胖子他们扯扯犊子,开阔一下视野用的。对于专业的技术知识来说,大家必须付出一个完整的时间段进行体系化学习,这样尊重知识,工资才能尊重你。 顺便说一句,我已经好久都不听罗胖子扯犊子了,刚开始办罗辑思维的时候觉得他扯的还可以,越往后越觉得都钻钱眼儿里了,天天在鼓吹焦虑,让大家去买他们的鸡汤课。不过听听矮大紧就挺好啊,不累~
  • 本小册是由 Markdown 写成,在电脑端阅读体验十分舒服,当然你非要用小手机看我也不拦着你,但是效果打了折扣是你的损失。
  • 为了保证最好的阅读体验,不用一个没学过的概念去介绍另一个新概念,本小册的章节有严重的依赖性,比如你在没读InnoDB数据页结构前千万不要就去读B+树索引,所以大家最好从前看到尾,不要跳着看!不要跳着看!不要跳着看!,当然,不听劝告我也不能说什么,祝你好运。
  • 大家可能买过别的小册,有的小册一篇文章可能用5分钟、10分钟读完,不过我的小册子每一篇文章都比较长,因为我把高耦合的部分都集中在一篇文章中了。文章中埋着各种伏笔,所以大家看的时候可能不会觉察出来很突兀的转变,所以在阅读一篇文章的时候千万不要跳着看!不要跳着看!不要跳着看!
  • 大家在看本小册之前应该断断续续看过一些与本小册内容相关的知识,只是不成体系,细节学习的不够。对于这部分读者来说,希望大家像倚天屠龙记里的张无忌一样,在学张三丰的太极剑法时先忘记之前的武功,忘的越干净,学的越得真传。这样才能跟着我的套路走下去。

如果你真的是个小白的话,那这里头的数字都是假的:

一篇文章能用2个小时左右的时间掌握就很不错了。说句扫大家兴的话,虽然我已经很努力的想让大家的学习效率提升n倍,但是不幸的是想掌握一门核心技术仍然需要大家多看几遍(不然工资那么好涨啊~)。

关于工具 #

本小册中会涉及很多 InnoDB 的存储结构的知识,比如记录结构、页结构、索引结构、表空间结构等等,这些知识是所有后续知识的基础,所以是重中之重,需要大家认真对待。Jeremy Cole 已经使用 Ruby 开发了一个简易的解析这些基础结构的工具,github地址是: innodb_ruby的github地址,大家可以按照说明安装上这个工具,可以更好的理解 InnoDB 中的一些存储结构(此工具虽然是针对MySQL 5.6的,但是幸好MySQL的基础存储结构基本没多大变化,所以大部分场景下这个innodb_ruby工具还是可以使用的)。

关于盗版 #

在写这本小册之前,我天真的以为只需要找几本参考书,看看 MySQL 的官方文档,遇到不会的地方百度谷歌一下就可以在 3 个月内解决这本书,后来的现实证明我真的想的太美了。不仅花了大量的时间阅读各种书籍和源码,而且有的时候知识耦合太厉害,为了更加模块化的把知识表述清楚,我又花了大量的时间来思考如何写作才能符合用户认知习惯,还花了非常多的时间来画各种图表,总之就是心累啊~ 我希望的是:各位同学可以用很低的成本来更快速学会一些看起来生涩难懂的知识,但是毕竟我不是马云,不能一心一意做公益,希望各位通过正规渠道获得小册,尊重一下版权。 还有各位写博客的同学,引用的少了叫借鉴,引用的多了就,就有点那个了。希望各位不要大段大段的复制粘贴,用自己的话写出来的知识才是自己的东西。 我知道不论我们怎样强调版权意识,总是有一部分小伙伴喜欢不劳而获,总是喜欢想尽各种渠道来弄一份盗版的看,希望这部分同学看完别忘了关注公众号【我们都是小青蛙】,给我填个粉儿也算是赞助一下我(下面是二维码,觉得有帮助的话希望可以打赏一下,毕竟本人很穷。另外,公众号中有若干篇小册的补充文章,包括三篇极其重要的语句加锁分析):

小贴士:我一直有个想法,就是如何降低教育成本。现在教育的盈利收费模式都太单一,就是直接跟学生收上课费,导致课程成为一种2C的商品,价格高低其实和内容质量并不是很相关,所以课程提供商会投入更大的精力做他们的渠道营销。所以现在的在线教育市场就是渠道为王,招生为王。我们其实可以换一种思路,在线教育的优势其实是传播费用更低,一个人上课和一千万人上课的费用区别其实就是服务器使用的多少罢了,所以我们可能并不需要那么多语文老师、数学老师,我们用专业的导演、专业的声优、专业的动画制作、专业的后期、专业的剪辑、专业的编剧组成的团队为某个科目制作一个专业的课程就好了嘛(顺便说一句,我就可以转行做课程编剧了)!把课程当作电影、电视剧来卖,只要在课程中植入广告,或者在播放平台上加广告就好了嘛,我们也可以在课程里培养偶像,来做一波粉丝经济。这样课程生产方也赚钱,学生们也省钱,最主要的是可以更大层度上促进教育公平,多好。

关于错误 #

准确性问题 #

我不是神,并不是书中的所有内容我都一一对照源码来验证准确性(阅读的大部分源码是关于查询优化和事务处理的),如果各位发现了文中有准确性问题请直接联系我,我会加入 Bug 列表中修正的。

...

01走进汉字世界

01走进汉字世界

封面 #

版权 #

版权信息

书名:汉字就是这么来的·走进汉字世界

作者:孟琢

出版社:湖南少年儿童出版社

出版时间:2020-08-01

ISBN:9787556251919

本书由天津博集新媒科技有限公司授权亚马逊发行

版权所有 侵权必究

logo

汉字的起源 #

汉字是中国文化的根源,蕴含着中华文明悠久古老的基因。当我们走进汉字世界的时候,先要思考一个重要的问题:汉字的源头是什么?

对这个问题的回答,真是众说纷纭。在历史上,有三种比较重要的说法:八卦造字、结绳造字和仓颉造字。

汉字与八卦 #

八卦,听起来蛮神奇的!中华民族的始祖伏羲氏[1]创造了八卦。他在大自然中看到了天空、大地、沼泽、大湖,还有清澈的水流、熊熊的烈火和浩浩荡荡的长风,听到了响彻苍穹的雷鸣。在伏羲看来,万事万物都分为阴阳,他用一个长横(i-)表示阳爻,用两个短横(i-)表示阴爻,再用阴阳进行组合,就拼出了八卦,分别代表天、地、山、泽、水、火、风、雷。

在中国文化中,八卦相当重要。有一部听起来有些神秘的古老经典——《周易》,就是以八卦的道理为根本的。于是,有人认为汉字也起源于八卦。他们举了一个很有意思的例子:在八卦中,有一个坎卦,表示水的意思。你看,坎卦是这个样子的:i-。主张汉字起源于八卦的人们说,把坎卦旋转九十度竖起来i-,和古文字中的i-(水)非常像。

你别说,对比一下还真像!那汉字真的起源于八卦吗?不是的,八卦中的另外七个卦和汉字一点儿关系也没有,样子也不相似。坎卦和水的相似,应该只是一种偶然。

结绳造字 #

还有一种说法,认为汉字起源于结绳。

什么叫作结绳呢?这是古人提醒自己别忘事的一种办法。他们随身携带一根绳子,有大事,就系一个大疙瘩,有小事,就系一个小疙瘩。这种风俗见于世界各地,有些比较原始的部落,现在还在使用结绳记事。

结绳能够帮助我们记事,汉字有同样的功能,于是有人认为,汉字起源于结绳。我们仔细想一想,就会发现这种说法并不靠谱——绳子上的疙瘩能提醒我们有一件重要的事,但它无法告诉我们,到底是什么事。你是要去上学呢?还是要去吃火锅呢?还是去游乐场玩耍呢?但汉字就不一样了,汉字能够传达准确而具体的信息。

仓颉:汉字的始祖 #

在造字的传说中,仓颉造字的说法流传最广。

仓颉是谁?相传他生活在公元前2500多年,距今有4500多年。仓颉是黄帝时期的史官,掌管着历史、文化与文献,这个身份和汉字的关系最为密切,古人认为是他发明了汉字。这个时间和我们今天发现的早期文字符号的时期,也是相当接近的。

根据一些古书中的记载,仓颉的样子很奇怪,“龙颜侈侈,四目灵光,实有睿德,生而能书”。这句话说的是,仓颉的额头很大,像龙一样,他有四个眼睛,绽放出闪闪的灵光,这个人非常聪明,生下来就能写字——哇,仓颉好厉害!

仓颉真长这个样子吗?不见得。古人习惯于将一些厉害的人物神化,来凸显他们的与众不同。他们往往出生时伴有奇怪的天象,长相也异于常人。伏羲是人的脑袋蛇的身子;蚩尤和兄弟们都是铜头铁额,真是够酷。没这么夸张,稍微低调一点儿的也有。三国时期的刘备双耳垂肩,双手过膝,耳垂和手的长度远非常人能比;明朝开国皇帝朱元璋脚上有七颗痣,有个厉害的说法叫作“脚踏七星”。所以,仓颉的长相也是经过了艺术的夸张。

仓颉是如何造字的呢?古代有一位大思想家叫韩非子,他记载了仓颉造字的一个思路,他说:“仓颉之作书也,自环者谓之私,背私者谓之公。”仓颉要给公开的“公”和自私的“私”造字。

先造“私”字,这个字的意思有点儿抽象,用什么样的字形来表达呢?想来想去,他找到了一个造字的好办法:画一个封闭的圆圈i-,圈里的东西都是我的,也就是“厶”。这个字是今天“私”字的右半边。在古人心中,什么东西最能表示私有呢?莫过于粮食!于是,聪明的古人在“厶”旁边再添加一个“禾”,创造出“私”,强调这是我私有的财物。

“私”造出来了,“公”又该如何造字呢?这个问题难不住聪明的仓颉!他说,“公”和“私”的意思是相反的,把私有的财物分给大家,不就是“公”嘛。因此,他在“厶”的上面加上了一个“八”字。在数字中,一分为二,二分为四,四分为八,都是一个不断分离的过程。因此“八”表示分的意思,把“私”用“八”不断分开,这就是“公”!

仓颉造字,体现出高超的智慧!事实上,汉字不可能是某一个人造出来的,中华民族宝贵的文化遗产,是人民大众的智慧结晶。战国的大思想家荀子点明了仓颉造字的实质。《荀子》中说:“好书者众矣,而仓颉独传者,壹也。”喜欢写字、善于造字的人很多,但只有仓颉造字的名声千古流传,这是为什么呢?因为仓颉“专壹”!

请注意,大写的“壹”字,既表示专一,仓颉一心一意地创造汉字;也表示规范、整理与统一的意思。仓颉是汉字的整理者、规范者与统一者,他是古人发明汉字的伟大的历史运动中的代表。

正因如此,仓颉被后人尊称为“字圣”——发明汉字的圣人。

随着汉字的发明,我们的历史文化大大地向前迈了一步。相传汉字发明之后,“天雨粟,鬼夜哭”——天上落下粮食雨,晚上有鬼在哭泣,听上去是不是有点儿恐怖呢?事实上,“天雨粟,鬼夜哭”是个吉兆呢!上天降下粮食雨,奖励人们发明了汉字;鬼也不是可怕的妖怪,所谓“鬼者,归也”,他们是“回归”故乡的祖先灵魂。那些去世的祖先觉得,有了汉字,他们的生平事迹就会被记录在文字里,再也不会被后人遗忘了,因此纷纷喜极而泣。

汉字源自图画 #

传说听起来很热闹,但如果根据考古来看,汉字应当起源于早期的原始图画。大家跟我看大汶口文化的图画型陶符,以及半坡文化中的彩陶符号。在这些刻画在陶器上的符号中,有圆圆的太阳,有巍峨的高山,有抽象的小草……和汉字中的象形文字,真是如出一辙。

...

人間道

校 堪 序 #

本《人间道》乃由民间的中医爱好者整理与校对。中华民族文化博大精深、渊远流长,中医更是中华民族的瑰宝,几千年来一直守护着炎黄子孙的健康。继承和发扬中医,本是我们爱好中医人士与生俱来的使命。可是由于种种原因,使得中医的许多典籍在流传上产生问题;或已出版而校对欠佳,或印量稀少而极难购得,甚或已经绝版而失传。使得这份本应属于整个中华民族所共有共享的珍贵智慧,无法让更多需要的人学习它,大非往圣之本意!

我们在校正的过程中,仅对明显的错别字给予了修改,对于无法确定者则保留原样。我们力图提供正确无误的电子书,但限于能力,自知错误在所难免。

本书的原始材料来自于网络,为网络中善心人士传播之电子版本。本书的校正, 由民间中医爱好朋友们自发组织,属于无偿的自发行为,在此首先对他们表示感谢! 本电子版不收取任何费用,亦不得将本书内容用于商业行为。

根据相关法律,本电子书仅供网络测试,不收取任何费用。请您下载后 24 小时内删除,如果您喜欢本书,请购买原版。任何人不得将本书用于商业行为,否则由此直接或间接引发的任何法律问题,我们不承担责任。

民间中医爱好者 敬校

2010-10-22

自 序

本書之著作,是為了發揚我國千年來,易經的神髓而作的,目的是希望後代子孫能以中國文化為榮,以身為炎黃子孫為傲,切不可數典忘袓,唯有真正的發揚固有文化,才可以讓中國人領導二十一世紀,獨領風騷。

本書之書名,是由我父親倪志凌先生親手寫的,我父親飽讀詩書,現旅居美國, 一手好字,為同仁所公認,他一直以中國人為榮,時時教诲他的孫子,不可忘本, 從小我就受他影響很大,萬般皆下品,惟有讀書高的觀念,三日不讀書,面目可憎, 真是如此。現在社會形態一直轉變,我從事算命有十幾年,看盡人間百態有感而發, 希望藉由此著作,能寓教於人,不可再茫然度日,只知吃喝玩樂,不知長進。做長輩的要求子女多讀書,而不以身作則,人言:言教不如身教。我愛讀書,喜歡研究, 實身受我父親影響至大,故特別請我父親為我的書名立文,以茲感念。

梵宇龍八十三年九月十日

自 序

易,變易也,隨時變易以從道也。

不易也,事物之外象皆變,而其理不變也。簡易也,萬法皆不同,然其神只有一也。

故易廣大皆備,順性命之理,通陰符,盡事物之情,而示吾人開物成務之道。得此易道之神,則天下萬事皆能化繁為簡矣。

前賢失其義而只能傳其言,後學者誦言而忘其味。自秦以後,無傳矣。前有天官,姜太公、范蠡、鬼谷子、張良、諸葛亮、李淳風、程頤、邵康節、劉伯温之用易,其用易之神,後學者瞠乎其後,而實無來者再傳其神矣。

易中聖人之道有四:以言者,尚其辭。以動者,尚其變。制器者,尚其象。卜筮者,尚其占。其間藴含吉凶消長之理,進退存亡之道。

君子靜則觀象以悟其辭,動則觀變以玩其占。

今世之人,大都得其辭,而未達其意,此著作以悟象之角度申其義,此其目的也。

祈與同道共勉之!

作者倪海廈甲戍年正月廿四日

郭 序

易經一書,相傳始於伏羲,成於文王。爲古人仰觀天象,俯察地理,累積日常生活資料所得之經驗。稱之為易,蓋取其〔簡易、變易、不易〕。因其簡易,當為常人所了解;因其變易,當可用於事事,復因不易,當能垂教萬世。唯以書成年代久遠,用語艱澀隱晦,不易暸解,師徒口語相傳,又失其微言大義,加以今人多不識此書,或竟視爲算命工具,或直斥爲迷信,殊為可惜。

畏友 海廈兄,自幼隨明師習醫,於吾國固有之〔山、醫、命、相、卜〕諸術, 無不精通,尤擅於易經,除熟讀探究易經精義,更已將易經融入日常生活中,經由具體之實驗,驗證先哲思想之正確性。而余生也駑鈍,自倖入法界服務以來,對案件之偵査,雖期能究明實情,勿枉勿縱,但驗諸實際,每感實質正義追求之不易與人道之難爲,挫折感屢生,適因緣際會得識 海廈兄,每以易經象術相教,既解迷惑於一時,復啟對問題思考之另一模式,助益可謂大矣。

今兄將研習易經多年之心得與課堂講授之經驗,集數月之力,爲十餘萬言,著成此書,以簡淺文字,發前人之所未言,闡明易經之微言大義;又博採史例,廣爲佐引,論證古今,詳實可信。於書成之際,邀余爲序,爰不揣淺陋做之序,以示慶賀之意,更盼巨著隨出,以享讀者。

中 華 民 國 八十三年十一月九日

郭學廉 序於台灣板橋地方法院檢察署

徐 序

人生於天地之間,秉天地之氣而有形,受天地之養以爲生。未有能離於天地之

間而生者。是倪師海廈畢數十年之心力,上窮天道,下探地脈,中明人事,終底於成,而作「天紀」。

余不敏,早歲亦嘗涉獵易理,惟不得法鬥。自從倪師游,方知易者「易」也, 何「難」之有?亦知吾國先人之智慧至倪師而能昭顯。「天紀」一書,以易經爲軸, 以天文、地理及人間道爲輔;發前人之所未發,言前人之所未言。復道盡天、人、地三才之關係,良以三才能分,能合;名異而實爲一體也。又豈天人合一之境所能比擬?

吾國易經博大精深,漢、唐以前,重象、數而輕辭,自宋以降,則重辭而輕象、 數。倪師則並重之。使「天紀」一書不僅成爲集古代易經之大成,更有所發明。例如,,倪師之陽宅學,以九宮八卦圖爲内卦,居於其位之人爲外卦;卦既成,則觀該卦之象以斷其人之吉凶禍福。此實深合易之道也。

君子静以觀象,退而演易,動則問卜,以果決行。「天紀」一書實爲倪師智慧之結晶,若以卜筮之流者視之,吾不與焉!

徐光佑甲戍年孟冬 序於 台北景美

前 言

本書的內容,共分二部份。〔一〕從圖來談易經,即古人所謂「無字天書」,占卜、問卦,也可以應用於易經推命來批流年行運,也可以運用於陽宅來推易,這是學如何演易。〔二 〕從易辭部份來研究「人間道」。從第一卦「乾為天」開始,天地定位後,人的一生即進入此一輪迴,舉凡天地間所有的任何事物,全部包羅在內, 不但是醒世哲言,更可將世間所有的學問理論簡化之。今人讀易越讀越複雜,或是講易經講半天,而無人懂,這都是未得易之道,所謂易者,易也,不然何名「易經」?

讀易的心理準備

易經本身並不難,故讀者先要有一概念,在讀易之前,平心静氣,捨去一切雜念,千萬不可在讀易之前,先對易經有所認定,那尚未開始,您已經錯了 , 一步錯,步歩錯,一旦離開了易經的神,運氣好的要「十年乃字」〔十年乃數之終,有倦怠的象〕,運氣不好,又自以為是的話,可能終其一世,仍未窺得易之全貌。

...

64火水未濟

64火水未濟 #


此卦孔子穿九曲明珠未徹,卜得之,乃遇二女方始得穿也。

圖中:

一人提刀斧,一虎坐,一旗卓在山上, 一人取旗,梯子有到字。

碣火求珠之課 憂中望喜之象

物必不會終盡,故以未濟為易卦之終。既濟為物之終,易為變易而不盡,有生生之意,故未濟為其序。未濟為未窮盡也,此卦,上離下坎,火在水上,互不為用,為未濟之時義。

卦圖象解

一、一人提刀斧:劉姓,武官,手有生殺之權。二、 一虎坐:肖虎人,王姓,虎坐乃無威之象。三、一旗卓在山上:揭竿而起,正義之師。

四、一人取旗:代替也,高姓,宋姓,其人取代之象。

五、梯子有至字:無刀日至,桎梏受困象,六、(附註:峪:谷姓。旗揚:楊姓。)有谷、楊合乃招凶象。

人間道

未濟:亨。小狐汔濟,濡其尾,无攸利。

未濟之時,亦有亨通之道。假如小狐不知慎,逞其壯勇,渡河不知慎,其終必不能濟,故無所利矣。

彖曰:未濟亨,柔得中也。小狐汔濟,未出中也。 #

未濟之時,能亨通,乃因其柔居中得其時,慎處之於未濟時,可以亨通也。如小狐之果敢於渡河,如不憂其尾濕,必不可脱險也。

濡其尾,无攸利,不續終也。雖不當位,剛柔應也。 #

其進雖勇,因尾濡而不能進,故不利往也。若能慎重處之,剛柔並濟則雖不當位,亦有可濟之理處。

象曰:火在水上,未濟,君子以愼辨物居方。 #

火在水上,互不相交,此為未濟,君子觀象知,乃處不當之象,應慎處事物,辨其所當, 各居其位,止於其所。

初六:濡其尾,吝。 #

陰柔居下位,居未濟之時,求力進猶獸之渡河,必揭其尾,方可渡,此言人不度量其才而進,終必不濟,終招吝鄙也。

九二 :曳其輪,貞吉。 #

陽剛居將位,有欲動之象,今居未濟之時, 有以剛凌柔水來勝火之象,故須知止,如曳車之輪使其止進,如此可吉。戒之在剛過,如此則犯上,其終必凶。

六三:未濟,征凶,利涉大川。 #

居未濟之時,柔居相位,在下卦之上,有領導之象,但才不足濟,居險而無才足以出險, 如此而行,其必招凶致。惟俟時至,俟上位之才相應,再涉險而出,乃可出險。

九四:貞吉 ,悔亡,震用伐鬼方, 三年有賞于大國。 #

陽剛之賢才,居於君側,上為中虛明順之君,故能濟天下之艱困,能伐鬼方示其力之大, 三年後乃有大功受國封賞。

六五:貞吉 ,无悔,君子之光, 有孚,吉。 #

中虛而明之才居君之尊位,能虛其心任剛賢之相為輔佐,且信任之而不悔,此處之至善, 即令己才不足,但亦由中心孚誠,終必大吉。

象曰:君子之光,其暉吉也。 #

上九:有孚于飲酒,无咎,濡其首, 有孚失是。

陽剛居極,在中虛卦之上,乃示其剛且明, 能如此,則必不生燥,決之以明,明能洞察事理,剛能行事,然居未濟之時,因無可濟之理, 故成樂天順命而已,可以無災。如過於禮法, 濡其首,亂如是,其必不知反省,則示不安於所居也。

...