MySQL理论

MySQL理论

MySQL数据库基础

MySQL与MariaDB

1)MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB(英语:XtraDB)来代替MySQL的InnoDB。
2)MariaDB由MySQL的创始人Michael Widenius(英语:Michael Widenius)主导开发,他早前曾以10亿美元的价格,将自己创建的公司MySQL AB卖给了SUN,此后,随着SUN被甲骨文收购,MySQL的所有权也落入Oracle的手中。MariaDB名称来自Michael Widenius的女儿Maria的名字。
3)MariaDB基于事务的Maria存储引擎,替换了MySQL的MyISAM存储引擎,它使用了Percona的XtraDB,InnoDB的变体,分支的开发者希望提供访问即将到来的MySQL 5.4 InnoDB性能。这个版本还包括了PrimeBase XT (PBXT) 和 FederatedX存储引擎。

MySQL数据类型

image-20220620151041921

数据库类型的使用

M为0~65535之间的整数1)整数类型
tinyint(极小的整数)、smallint(小的整数)、mediumint(中等大小的整数)、int(普通大小的整数)、bigint(极大的整数)

2)小数类型
float(单精度浮点数)、double(双精度浮点数)、decimal(m,d)(压缩严格的定点数,一般用于记录货币,m表示一共多少位,d表示小数点保留几位)

3)日期类型
year(YYYY,范围1901~2155)、time(HH:MM:SS,范围-838:59:59~838:59:59)、date(YYYY-MM-DD,范围1000-01-01~9999-12-3)、datetime(YYYY-MM-DD HH:MM:SS,范围1000-01-01 00:00:00~ 9999-12-31 23:59:59)、timestamp(YYYY-MM-DD HH:MM:SS,范围19700101 00:00:01 UTC~2038-01-19 03:14:07UTC,以时间戳格式存储,一般使用timestamp储存时间,空间效率高于datetime)

4)文本、二进制类型
CHAR(M)(M为0~255之间的整数)、VARCHAR(M)(M为0~65535之间的整数)、TINYBLOB(允许长度0~255字节)、BLOB(允许长度0~65535字节,可用于保存图片base64格式)、MEDIUMBLOB(允许长度0~167772150字节)、LONGBLOB(允许长度0~4294967295字节)、TINYTEXT(允许长度0~255字节)、TEXT(允许长度0~65535字节)、MEDIUMTEXT(允许长度0~167772150字节)、LONGTEXT(允许长度0~4294967295字节)、VARBINARY(M)(允许长度0~M个字节的变长字节字符串)、BINARY(M)(允许长度0~M个字节的定长字节字符串)、ENUM(把不重复的数据存储为一个预定义的集合,ENUM在内部存储时,其实存的是整数,尽量避免使用数字作为ENUM枚举的常量,因为容易混乱。排序是按照内部存储的整数,即('男','女','未知')会对应0,1,2。)

MySQL约束类型

真正约束字段的是数据类型,但是数据类型约束很单一,需要有一些额外的约束,更好的保证数据的合法性,从业务逻辑角度保证数据的正确性。数据库约束主要分为:
1)主键约束(PRIMARY KEY,非空和唯一的结合),确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录。
2)唯一约束(UNIQUE),保证某列的每行必须有唯一的值。
3)默认约束(DEFAULT),规定没有给列赋值时的默认值。
4)检查约束(CHECK),保证列中的值符合指定的条件。
5)外键约束(FOREIGN KEY),保证一个表中的数据匹配另一个表中的值的参照完整性。
6)非空约束(NOT NULL),指示某列不能存储 NULL 值。

DDL、DML、DQL、TCL

1)数据定义语言(DDL)
CREATE:在数据库中创建新的数据对象
ALTER:修改数据库中对象的数据结构
DROP:删除数据库中的对象
DISABLE/ENABLE TRIGGER:修改触发器的状态
UPDATE STATISTIC:更新表/视图统计信息
TRUNCATE TABLE:清空表中数据
COMMENT:给数据对象添加注释
RENAME:更改数据对象名称

2)数据操作语言(DML)
INSERT:将数据插入到表或视图
DELETE:从表或视图删除数据
SELECT:从表或视图中获取数据
UPDATE:更新表或视图中的数据
MERGE:对数据进行合并操作(插入/更新/删除)

3)数据控制语言(DCL)
GRANT:赋予用户某种控制权限
REVOKE:取消用户某种控制权限

4)事务控制语言(TCL)
COMMIT:保存已完成事务动作结果
SAVEPOINT:保存事务相关数据和状态用以可能的回滚操作
ROLLBACK:恢复事务相关数据至上一次COMMIT操作之后
SET TRANSACTION:设置事务选项

存储过程、触发器、视图

储存过程与触发器详解:https://juejin.cn/post/7161662496460242980#heading-26

1)存储过程:是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。

2)触发器:是用户定义在关系表上的一类由事件驱动的特殊的存储过程。触发器是指一段代码,当触发某个事件时,自动执行这些代码。在MySQL数据库中有如下六种触发器:Before Insert、After Insert、Before Update、After Update、Before Delete、After Delete。

3)视图:视图只能进行数据查询,增删改数据需要去操作它相关的基本表。为了提高复杂SQL语句的复用性和表操作的安全性,MySQL数据库管理系统提供了视图特性。所谓视图,本质上是一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据。但是,视图并不在数据库中以储存的数据值形式存在。行和列数据来自定义视图的查询所引用基本表,并且在具体引用视图时动态生成。

-- 创建视图(stu_v_1是视图名称,as后面是视图语句)
create or replace view stu_v_1 as select id,name from student where id <= 10;
或
create view stu_v_1 as select id,name from student where id <= 10;

-- 查看创建视图语句
show create view stu_v_1;
-- 查看视图数据
select * from stu_v_1;
select * from stu_v_1 where id < 3;

-- 修改视图
create or replace view stu_v_1 as select id,name,stuno from student where id <= 10;
或
alter view stu_v_1 as select id,name from student where id <= 10;

-- 删除视图
drop view if exists stu_v_1;

IN和EXISTS

-- 如果查询的两个表大小相当,那么用in和exists差别不大
-- 如果两个表中一个较小,一个是大表,则子查询表(即B表)大的用exists,子查询表小的用in
-- 如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not extsts的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快
select * from A where id in(select id from B);
select a.* from A a where exists(select 1 from B b where a.id=b.id)

VARCHAR与CHAR

VARCHAR:表示可变长字符串,长度是可变的,插入的数据是多长,就按照多长来存储,它存取慢,因为长度不固定,但正因如此,不占据多余的空间,是时间换空间的做法,对于VARCHAR来说,最多能存放的字符个数为65532。

CHAR:表示定长字符串,长度是固定的,如果插入数据的长度小于char的固定长度时,则用空格填充,因为长度固定,所以存取速度要比varchar快很多,甚至能快50%,但正因为其长度固定,所以会占据多余的空间,是空间换时间的做法,对于char来说,最多能存放的字符个数为255,和编码无关。

区别主要有以下几个方面
1、最大长度:char最大长度是255字符,varchar最大长度是65535个字节。
2、定长:char是定长的,不足的部分用隐藏空格填充,varchar是不定长的。
3、空间使用:char会浪费空间,varchar会更加节省空间。char类型会预先分配一定长度的空间,而varchar类型则根据实际存储的字符串长度动态分配空间。例如,如果定义一个char(50)类型的列,那么无论实际存储的字符串长度是多少,都会占用50个字符的空间;而如果定义一个varchar(50)类型的列,那么实际占用的空间将取决于存储的字符串长度,不会浪费空间。
4、查找效率:char查找效率会很高,varchar查找效率会更低。由于char类型的数据长度是固定的,因此在查询时效率更高,因为MySQL可以直接根据偏移量计算出每个字符在磁盘上的位置,而不需要像varchar类型那样需要先遍历整个字符串才能确定位置。
5、插入和更新效率:由于char类型的数据长度是固定的,因此在插入和更新数据时,如果实际存储的字符串长度小于指定长度,那么MySQL会使用空格字符填充剩余的空间,这可能会浪费一些存储空间。而varchar类型则可以动态分配空间,不会浪费空间。
6、使用场景:由于char类型在存储和查询时效率更高,因此适用于存储长度固定的数据,例如身份证号、邮政编码等;而varchar类型则适用于存储长度不确定的数据,例如用户名、地址等。在项目中的使用,这两种方式都会用到,比如像一些枚举值是固定长度的可以使用char,像一些描述信息或名字类的长度不固定的选择使用varchar。

VARCHAR(50)和INT(20)

varchar(50):50是指最多存放50个字符,varchar(50)和(200)存储hello所占空间一样,但后者在排序时会消耗更多内存,因为order by col采用fixed_length计算col长度(memory引擎也一样)。在早期MySQL版本中,50代表字节数,现在代表字符数。

INT(20):20是指显示字符的长度。20表示最大显示宽度为20,但仍占4字节存储,存储范围不变;不影响内部存储,只是影响带zerofill定义的int时,前面补多少个0,易于报表展示。这里显示的宽度和数据类型的取值范围是没有任何关系的,显示宽度只是指明Mysql最大可能显示的数字个数,数值的位数小于指定的宽度时会由空格填充;如果插入了大于显示宽度的值,只要该值不超过该类型的取值范围,数值依然可以插入,而且能够显示出来。对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均一样。

MySQL查询语句执行顺序

sql的编写顺序:select字段列表、distinct去重、from表名列表、join on表关联、where条件列表、group by分组字段列表、having分组后的条件列表、order by排序字段列表、limit分页参数。

sql的执行顺序:from表名列表、join on表关联、where条件列表、group by分组字段列表、having分组后的条件列表、select字段列表、distinct去重、order by排序字段列表、limit分页参数。

举例:
select name ,age from tb_user where name = '张三' order by age limit 10;
给表起别名
select u.name ,u.age from tb_user u where name = '张三' order by u.age limit 10;
可以正常执行,如果from后不先执行,则select和order by无法引用
给sql的字段起别名
select u.name uname ,u.age uage from tb_user u where uname= '张三' order by u.age limit 10;
在where之后使用别名,执行报错,因为where在select之前执行
select u.name uname ,u.age uage from tb_user u where u.name= '张三' order by uage limit 10;
在order by后面使用别名,可以正常执行,因为select执行完成后才会执行order by 

MySQL存储引擎

MySQL存储引擎分类

数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。存储引擎主要有:MyIsam、InnoDB、Memory、Archive、Federated等。

1)ISAM:ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。ISAM的两个主要不足之处在于,它不支持事务处理,也不能够容错:如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把ISAM用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,MYSQL能够支持这样的备份应用程序。
2)MyIsam:MyISAM是MySQL的ISAM扩展格式和缺省的数据库引擎。除了提供ISAM里所没有的索引和字段管理的大量功能,MyISAM还使用一种表格锁定的机制,来优化多个并发的读写操作,其代价是你需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的空间。MyISAM还有一些有用的扩展,例如用来修复数据库文件的MyISAMCHK工具和用来恢复浪费空间的MyISAMPACK工具。MYISAM强调了快速读取操作,这可能就是为什么MySQL受到了WEB开发如此青睐的主要原因:在WEB开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和INTERNET平台提供商只允许使用MYISAM格式。MyISAM格式的一个重要缺陷就是不能在表损坏后恢复数据。
3)InnoDB:InnoDB数据库引擎都是造就MySQL灵活性的技术的直接产品,这项技术就是MYSQL+API。在使用MYSQL的时候,你所面对的每一个挑战几乎都源于ISAM和MyISAM数据库引擎不支持事务处理(transaction process)也不支持外来键。尽管要比ISAM和MyISAM引擎慢很多,但是InnoDB包括了对事务处理和外来键的支持,这两点都是前两个引擎所没有的。
4)Memory(也叫HEAP):HEAP允许只驻留在内存里的临时表格。驻留在内存里让HEAP要比ISAM和MYISAM都快,但是它所管理的数据是不稳定的,而且如果在关机之前没有进行保存,那么所有的数据都会丢失。在数据行被删除的时候,HEAP也不会浪费大量的空间。HEAP表格在你需要使用SELECT表达式来选择和操控数据的时候非常有用。要记住,在用完表格之后就删除表格。
5)Archive、Federated:略

InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定。基本的差别为:
1)MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。
2)MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持以及外部键等高级数据库功能。
MyISAM适合:做很多count的计算;插入不频繁,查询非常频繁;没有事务。
InnoDB适合:可靠性要求比较高,或者要求事务;表更新和查询都相当的频繁,并且表锁定的机会比较大的情况。

MyISAM只支持表锁,InnoDB支持表锁、行锁,行锁大幅度提高了多用户并发操作的性能,但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的。另外InnoDB支持事务的操作,而MyISAM则不支持。MySql能够允许你在表这一层应用数据库引擎,所以你可以只对需要事务处理的表格来进行性能优化,而把不需要事务处理的表格交给更加轻便的MyISAM引擎。对于MySql而言,灵活性才是关键。

更换数据库存储引擎

1)查看数据库现在已提供什么存储引擎:show engines;
2)查看数据库当前默认的存储引擎:show variables like '%storage_engine%';
3)查看某个表用了什么引擎(在显示结果里参数engine后面的就表示该表当前用的存储引擎):show create table 表名;

-- 查看当前数据库支持的引擎
show ENGINES;

-- 修改数据库储存引擎
-- 全局生效,修改配置文件my.ini
在[mysqld]后面添加 default-storage-engine=InnoDB,重启服务,数据库默认的引擎修改为InnoDB。
-- 或在建表的时候指定
create table tableName (
id int primary key, name varchar(50)
) ENGINE=MyISAM;
-- 或建表后更改
alter table tableName ENGINE = InnoDB;

-- 查看当前数据库表储存引擎
show table status from tableName;
-- 或
show create table tableName;
-- 或使用第三方数据库管理工具查看

一条SQL的执行过程详解

db-mysql-sql-8

过程解析:

参考链接:https://pdai.tech/md/db/sql-mysql/sql-mysql-execute.html

1)驱动与连接池
在系统和MySQL进行交互之前,MySQL驱动会帮我们建立好连接,然后我们只需要发送SQL语句就可以执行CRUD了。一次SQL请求就会建立一个连接,多个请求就会建立多个连接。Java系统在通过MySQL驱动和MySQL数据库连接的时候是基于TCP/IP协议的,所以如果每个请求都是新建连接和销毁连接,那这样势必会造成不必要的浪费和性能的下降,也就说上面的多线程请求的时候频繁的创建和销毁连接显然是不合理的。使用数据库连接池可以维护一定的连接数,方便系统获取连接,使用就去池子中获取,用完放回去就可以了,我们不需要关心连接的创建与销毁,也不需要关心线程池是怎么去维护这些连接的。其实MySQL的架构体系中也已经提供了这样的一个池子,也是数据库连接池。双方都是通过数据库连接池来管理各个连接的,这样一方面线程之前不需要争抢连接,更重要的是不需要反复的创建的销毁连接。

2)线程处理
网络中的连接都是由线程来处理的,所谓网络连接说白了就是一次请求,每次请求都会有相应的线程去处理的。也就是说对于SQL语句的请求在MySQL中是由一个个的线程去处理的。MySQL中处理请求的线程在获取到请求以后获取SQL语句去交给SQL接口去处理。

3)查询解析器
SQL解析与优化是属于编译器范畴,和C等其他语言的解析没有本质的区别。其中分为,词法分析、语法和语义分析、优化、执行代码生成。

词法分析:词法分析主要是把输入转化成一个个Token,通常情况下,词法分析可以使用Flex来生成,但是MySQL并未使用该工具,而是手写了词法分析部分。其中Token中包含Keyword(也称symbol)和非Keyword。例如,SQL语句select username from userinfo,在分析之后,会得到4个Token,其中有2个Keyword,分别为select和from:
select(关键字)username(非关键字)from(关键字)userinfo(非关键字)

语法分析:语法分析就是生成语法树的过程。这是整个解析过程中最精华,最复杂的部分,不过这部分MySQL使用了Bison来完成。即使如此,如何设计合适的数据结构以及相关算法,去存储和遍历所有的信息,也是值得在这里研究的。如select username, ismale from userinfo where age > 20 and level > 5 and 1 = 1语句生成语法树如下图示。

4)查询优化器
MySQL会帮我去使用他自己认为的最好的方式去优化这条SQL语句,并生成一条条的执行计划,比如你创建了多个索引,MySQL会依据成本最小原则来选择使用对应的索引,这里的成本主要包括两个方面,IO成本和CPU成本。优化器执行选出最优索引等步骤后,会去调用存储引擎接口,开始去执行被MySQL解析过和优化过的SQL语句。

IO成本:即从磁盘把数据加载到内存的成本,默认情况下,读取数据页的IO成本是1,MySQL是以页的形式读取数据的,即当用到某个数据时,并不会只读取这个数据,而会把这个数据相邻的数据也一起读到内存中,这就是有名的程序局部性原理,所以MySQL每次会读取一整页,一页的成本就是1。所以IO的成本主要和页的大小有关,并且是顺序IO,不是随机IO。

CPU成本:将数据读入内存后,还要检测数据是否满足条件和排序等CPU操作的成本,显然它与行数有关,默认情况下,检测记录的成本是0.2。

5)执行器
执行器是一个非常重要的组件,因为前面那些组件的操作最终必须通过执行器去调用存储引擎接口才能被执行。执行器最终最根据一系列的执行计划去调用存储引擎的接口去完成SQL的执行。

6)存储引擎
UPDATE students SET stuName = '小强' WHERE id = 1
当我们系统发出查询去交给MySQL的时候,MySQL会按照我们上面的一系列的流程最终通过执行器调用存储引擎去执行。在执行这个SQL的时候,SQL语句对应的数据要么是在内存中,要么是在磁盘中,如果直接在磁盘中操作,那这样的随机IO读写的速度肯定让人无法接受的,所以每次在执行SQL的时候都会将其数据加载到内存中,这块内存就是InnoDB中一个非常重要的组件缓冲池Buffer Pool。

Buffer Pool(缓冲池):Buffer Pool是InnoDB存储引擎中非常重要的内存结构,顾名思义,缓冲池其实就是类似Redis一样的作用,起到一个缓存的作用,因为我们都知道MySQL的数据最终是存储在磁盘中的,如果没有这个Buffer Pool那么我们每次的数据库请求都会磁盘中查找,这样必然会存在IO操作,这肯定是无法接受的。但是有了Buffer Pool就是我们第一次在查询的时候会将查询的结果存到Buffer Pool中,这样后面再有请求的时候就会先从缓冲池中去查询,如果没有再去磁盘中查找,然后在放到Buffer Pool中,所以上面这条SQL语句的执行步骤大致是这样子的:InnoDB存储引擎会在缓冲池中查找id=1的这条数据是否存在,发现不存在,那么就会去磁盘中加载,并将其存放在缓冲池中,该条记录会被加上一个独占锁(防止在修改的时候被别人修改)。

undo日志文件:记录数据被修改前的样子。undo顾名思义,就是没有做,没发生的意思。undo log就是没有发生事情(原本事情是什么)的一些日志。在准备更新一条语句的时候,该条语句已经被加载到Buffer pool中了,实际上这里还有这样的操作,就是在将该条语句加载到Buffer Pool中的时候同时会往undo日志文件中插入一条日志,也就是将id=1的这条记录的原来的值记录下来。这样做的目的是因为Innodb存储引擎支持事务,如果本次更新失败,也就是事务提交失败,那么该事务中的所有的操作都必须回滚到执行前的样子,也就是说当事务失败的时候,也不会对原始数据有影响。

redo日志文件:记录数据被修改后的样子。除了从磁盘中加载文件和将操作前的记录保存到undo日志文件中,其他的操作是在内存中完成的,内存中的数据的特点就是:断电丢失。如果此时MySQL所在的服务器宕机了,那么Buffer Pool中的数据会全部丢失的,这个时候就需要redo日志文件。redo日志文件是InnoDB特有的,他是存储引擎级别的,不是MySQL级别的。redo记录的是数据修改之后的值,不管事务是否提交都会记录下来,例如,此时将要做的是update students set stuName='小强' where id=1; 那么这条操作就会被记录到redo log buffer中,因为MySQL为了提高效率,所以将这些操作都先放在内存中去完成,然后会在某个时机将其持久化到磁盘中。只要事务成功提交了,才会将最后的变更保存到数据库,在提交事务前仍然会具有相关的其他操作。将redo Log Buffer中的数据持久化到磁盘中,就是将redo log buffer中的数据写入到redo log磁盘文件中,一般情况下,redo log Buffer数据写入磁盘的策略是立即刷入磁盘。如果redo log Buffer刷入磁盘后,数据库服务器宕机了,但是这次数据就不会丢失了,因为redo log buffer中的数据已经被写入到磁盘了,已经被持久化了,就算数据库宕机了,在下次重启的时候MySQL也会将redo日志文件内容恢复到Buffer Pool中。刷磁盘可以通过innodb_flush_log_at_trx_commit参数来设置值为0表示不刷入磁盘,值为1表示立即刷入磁盘,值为2表示先刷到os cache。

bin log日志文件:记录整个操作过程。redo log是InnoDB存储引擎特有的日志文件,而bin log属于是MySQL级别的日志。redo log记录的东西是偏向于物理性质的,如:对什么数据,做了什么修改。bin log是偏向于逻辑性质的,类似于:对students表中的id为1的记录做了更新操作,两者的主要特点总结如下:
1、文件大小
redo log的大小是固定的(配置中也可以设置,一般默认的就足够了)。
bin log可通过配置参数max_bin log_size设置每个bin log文件的大小(但是一般不建议修改)。
2、实现方式
redo log是InnoDB引擎层实现的(也就是说是Innodb存储引擎独有的)。
bin log是MySQL层实现的,所有引擎都可以使用bin log日志。
3、记录方式
redo log采用循环写的方式记录,当写到结尾时,会回到开头循环写日志。
bin log通过追加的方式记录,当文件大小大于给定值后,后续的日志会记录到新的文件上。
4、使用场景
redo log适用于崩溃恢复(crash-safe)(这一点其实非常类似与Redis的持久化特征)。
bin log适用于主从复制和数据恢复。

bin log的刷盘是有相关的策略的,策略可以通过sync_bin log来修改,默认为0,表示先写入os cache,也就是说在提交事务的时候,数据不会直接到磁盘中,这样如果宕机bin log数据仍然会丢失。所以建议将sync_bin log设置为1表示直接将数据写入到磁盘文件中。刷入bin log有以下几种模式:
1、STATMENT:基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的SQL语句会记录到bin log中。优点:不需要记录每一行的变化,减少了 bin log 日志量,节约了 IO , 从而提高了性能。缺点:在某些情况下会导致主从数据不一致,比如执行sysdate()、sleep()等。
2、ROW:基于行的复制(row-based replication, RBR),不记录每条SQL语句的上下文信息,仅需记录哪条数据被修改了。优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨。
3、MIXED:基于STATMENT和ROW两种模式的混合复制(mixed-based replication, MBR),一般的复制使用STATEMENT模式保存bin log,对于STATEMENT模式无法复制的操作使用ROW模式保存bin log。

其实MySQL在提交事务的时候,不仅仅会将redo log buffer中的数据写入到redo log文件中,同时也会将本次修改的数据记录到bin log文件中,同时会将本次修改的bin log文件名和修改的内容在bin log中的位置记录到redo log中,最后还会在redo log最后写入commit标记,这样就表示本次事务被成功的提交了。如果在数据被写入到bin log文件的时候,刚写完,数据库宕机了,首先可以确定的是,只要redo log最后没有commit标记,说明本次的事务一定是失败的。但是数据是没有丢失了,因为已经被记录到redo log的磁盘文件中了。在MySQL重启的时候,就会将redo log中的数据恢复(加载)到Buffer Pool中。其实MySQL还会有一个后台线程,它会在某个时机将我们Buffer Pool中的脏数据刷到MySQL数据库中,这样就将内存和数据库的数据保持统一了。

语法树图示:

db-mysql-sql-parser-2

存储引擎图示:

db-mysql-sql-14

posted @ 2019-03-07 11:25  肖德子裕  阅读(866)  评论(0编辑  收藏  举报