MySQL是怎样运行的:(22)undo日志(上)
Session 22 undo日志(上)为了保证事务的原子性,当导致事务执行到一半就结束时,我们需要把情况改回原先的样子。这个过程就称之为==回滚==(英文名:rollback),这样就可以造成一个假象:这个事务看起来什么都没做,所以符合原子性要求。
每当我们要对一条记录做改动时(这里的改动可以指INSERT、DELETE、UPDATE),都需要留一手 —— 把回滚时所需的东西都给记下来。比方说:
你插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉
你删除了一条记录,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中
你修改了一条记录,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值
这些为了回滚而记录的内容称为撤销日志(undo日志),SELECT不需要相应的undo日志。
本章辅助表:
1234567CREATE TABLE undo_demo ( id INT NOT NULL, key1 VARCHAR(100), ...
MySQL是怎样运行的:(21)redo日志(下)
Session 21 redo日志(下)redo日志缓冲区的刷盘时机:
log buffer空间不足时。如果当前写入log buffer的redo日志量已经占满了log buffer总容量的大约一半左右,就需要把这些日志刷新到磁盘上
事务提交时。在事务提交时可以不把修改过的Buffer Pool页面刷新到磁盘,但是为了保证持久性,必须要把修改这些页面对应的redo日志刷新到磁盘(可通过系统变量innodb_flush_log_at_trx_commit控制)
后台有一个线程,大约每秒都会刷新一次log buffer中的redo日志到磁盘
正常关闭服务器时
做所谓的checkpoint时(稍后会仔细介绍)
磁盘上的redo日志文件不只一个,而是以一个日志文件组的形式出现的。这些文件以ib_logfile[数字](数字可以是0、1、2…)的形式进行命名。(详见文章)
redo日志文件格式
redo日志文件其实也是由若干个512字节大小的block组成。redo日志文件组中的每个文件大小都一样,格式也一样,都是由两部分组成:
前2048个字节,也就是前4个block是用来存储一些管理信 ...
MySQL是怎样运行的:(20)redo日志(上)
Session 20 redo日志(上)在介绍事务的时候又强调过一个称之为持久性的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所做的更改也不能丢失。
假设突然发生了某个故障,导致内存中的还没刷入的数据都失效了,那么这个已经提交了的事务对数据库中所做的更改也就跟着丢失了。那么如何保证这个持久性呢?一个很简单的做法就是【在事务提交的同时把该事务所修改的所有页面都刷新到磁盘】。
但是这个简单粗暴的做法有些问题。有时候我们仅仅修改了某个页面中的一个字节,这样刷新一个完整的数据页太浪费了;有时一个事务可能包含很多语句,即使是一条语句也可能修改许多页面,如果这些页面不相邻,那么随机IO刷起来比较慢。
再次回到我们的初心:我们只是想让已经提交了的事务对数据库中数据所做的修改永久生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实没有必要在每次事务提交时就把该事务在内存中修改过的全部页面刷新到磁盘,只需要把修改了哪些东西记录一下就好。
redo日志格式
作为了解,我们没必要把InnoDB中的各种类型的redo日志格式都研究的透透的,目的是为了明 ...
MySQL是怎样运行的:(19)事务简介
Session 19 事务简介
事务的英文是transaction,英文直译就是交易,买卖的意思,交易就是买的人付钱,卖的人交货,不能付了钱不交货,交了货不付钱把,所以交易本身就是一种不可分割的操作。不知道是哪位大神把transaction翻译成了事务(我想估计是他们也想不出什么更好的词儿,只能随便找一个了),事务这个词儿完全没有交易、买卖的意思,所以大家理解起来也会比较困难,外国人理解transaction可能更好理解一点吧
为了让某些数据库操作符合现实世界中状态转换的规则,设计数据库的大佬们总结了几条规则。
==原子性(Atomicity)==
现实世界中转账操作是一个不可分割的操作,也就是说要么压根儿就没转,要么转账成功,不能存在中间的状态。**这种要么全做,要么全不做的规则称之为原子性**。但是在现实世界中的一个不可分割的操作却可能对应着数据库世界若干条不同的操作,数据库中的一条操作也可能被分解成若干个步骤(比如先修改缓存页,之后再刷新到磁盘等),最要命的是在任何一个可能的时间都可能发生意想不到的错误(可能是数据库本身的错误,或者是操作 ...
MySQL是怎样运行的:(18)InnoDB的Buffer Pool
Session 18 InnoDB的Buffer Pool当需要访问某个页的数据时,InnoDB存储引擎就会把完整的页的数据全部加载到内存中(即使我们只需要访问一个页的一条记录)。在进行完读写访问之后并不着急把该页对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省去磁盘IO的开销了。
在MySQL服务器启动时向操作系统申请了一片连续的内存,叫做Buffer Pool(中文名是缓冲池)。默认情况下Buffer Pool有128M大小,允许用户调整。
12[server]innodb_buffer_pool_size = 268435456
为了更好的管理这些在Buffer Pool中的缓存页,设计InnoDB的大佬为每一个缓存页都创建了一些所谓的控制信息,包括了【该页所属的表空间编号、页号、缓存页在Buffer Pool中的地址、链表节点信息、一些锁信息以及LSN信息】。
控制信息占用的一块内存称为一个控制块,控制块和缓存页是一一对应的,它们都被存放到 Buffer Pool 中,其中控制块被存放到 Buffer Pool 的前面,缓存页被存放到 Buff ...
MySQL是怎样运行的:(11)连接的原理
Session 11 连接的原理连接的本质就是把各个连接表中的记录都取出来依次匹配的组合加入结果集并返回给用户。所以我们把t1和t2两个表连接起来的过程如下图所示:
1mysql> SELECT * FROM t1, t2; # 只要在FROM语句后边跟多个表名就好了(内连接)
这个过程看起来就是把t1表的记录和t2的记录连起来组成新的更大的记录,所以这个查询过程称之为连接查询。连接查询的结果集中包含一个表中的每一条记录与另一个表中的每一条记录相互匹配的组合,像这样的结果集就可以称之为笛卡尔积。
比如对于如下语句:
1234567891011121314151617mysql> SELECT * FROM t1;+------+------+| m1 | n1 |+------+------+| 1 | a || 2 | b || 3 | c |+------+------+mysql> SELECT * FROM t2;+------+------+| m2 | n2 |+------+------+| ...
MySQL是怎样运行的:(10)单表访问方法
Session 10 单表访问方法本章的辅助表:
123456789101112131415CREATE TABLE single_table ( id INT NOT NULL AUTO_INCREMENT, key1 VARCHAR(100), key2 INT, key3 VARCHAR(100), key_part1 VARCHAR(100), key_part2 VARCHAR(100), key_part3 VARCHAR(100), common_field VARCHAR(100), PRIMARY KEY (id), KEY idx_key1 (key1), UNIQUE KEY idx_key2 (key2), KEY idx_key3 (key3), KEY idx_key_part(key_part1, key_part2, key_part3)) Engine=InnoDB CHARSET=utf8;
UNIQUE KEY idx_key2 (key2)索引要求索引列key2的值 ...
MySQL是怎样运行的:(9)InnoDB的表空间
Session 9 InnoDB的表空间本章概括:
本章会总览==页的类型==。为了方便,称呼类型时省略前缀FIL_PAGE_TYPE_。
类型名称
十六进制
描述
FIL_PAGE_TYPE_ALLOCATED
0x0000
最新分配,还没使用
FIL_PAGE_UNDO_LOG
0x0002
Undo日志页
FIL_PAGE_INODE
0x0003
段信息节点
FIL_PAGE_IBUF_FREE_LIST
0x0004
Insert Buffer空闲列表
FIL_PAGE_IBUF_BITMAP
0x0005
Insert Buffer位图
FIL_PAGE_TYPE_SYS
0x0006
系统页
FIL_PAGE_TYPE_TRX_SYS
0x0007
事务系统数据
FIL_PAGE_TYPE_FSP_HDR
0x0008
表空间头部信息
FIL_PAGE_TYPE_XDES
0x0009
扩展描述页
FIL_PAGE_TYPE_BLOB
0x000A
BLOB页
FIL_PAGE_ ...
MySQL是怎样运行的:(8)MySQL的数据目录
Session 8 MySQL的数据目录像InnoDB、MyISAM这样的存储引擎都是把表存储在磁盘上的,而操作系统用来管理磁盘的那个东东又被称为文件系统,所以用专业一点的话来表述就是:像 InnoDB 、 MyISAM 这样的存储引擎都是把表存储在文件系统上的。当我们想读取数据的时候,这些存储引擎会从文件系统中把数据读出来返回给我们,当我们想写入数据的时候,这些存储引擎会把这些数据又写回文件系统。
安装目录包含控制客户端程序和服务器程序的命令(bin目录下),而数据目录是用来存储MySQL在运行过程中产生的数据,一定要区分开。
123456mysql> SHOW VARIABLES LIKE 'datadir';+---------------+-----------------------+| Variable_name | Value |+---------------+-----------------------+| datadir | /var/lib/mysql/ | # 通常应该是/us ...
MySQL是怎样运行的:(7)B+树索引的使用
Session 7 B+树索引的使用一个表上索引建的越多,就会占用越多的存储空间,在增删改记录的时候性能就越差。为了能建立又好又少的索引,我们需要了解这些索引在哪些条件下起作用的。
本章的辅助表:
123456789CREATE TABLE person_info( id INT NOT NULL auto_increment, name VARCHAR(100) NOT NULL, birthday DATE NOT NULL, phone_number CHAR(11) NOT NULL, country varchar(100) NOT NULL, PRIMARY KEY (id), KEY idx_name_birthday_phone_number (name, birthday, phone_number));
全值匹配
我们的搜索条件中的列和索引列一致的话,这种情况就称为全值匹配。
1SELECT * FROM person_info WHERE birthday = '1990-09-27' AND ph ...