vlambda博客
学习文章列表

Mysql 原理详解(一):日志索引事务篇







小·引






关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。用户通过查询来检索数据库中的数据,而查询是一个用于限定数据库中某些区域的执行代码。关系模型可以简单理解为二维表格模型,而一个关系型数据库就是由二维表及其之间的关系组成的一个数据组织。主流的关系型数据库有Oracle、DB2、MySQL、Microsoft SQL Server、Microsoft Access。

01

Mysql-日志篇

Redo log

每次更新操作的都要写进磁盘,先是要在数据库中找到那条记录,然后再更新,每次的IO 成本都很高,为了解决这个问题就有了先写日志在写磁盘的骚操作。也就是 WAL(Write-Ahead Logging)技术,实现的关键点就是 先写日志在写磁盘。提供了 safe-cash,将磁盘随即写转变为顺序写,提高性能。因此 redo log 应运而生。

redo log 是一个环形的结构,write_pos 是当前要写的位置,check_point 是已写入磁盘的同步点,在工作时候,wirte_pos 往前写,check_poiont 也在往前同步。

Mysql 原理详解(一):日志索引事务篇

Bin log

mysql 位于 Service 的日志系统,bin log(归档日志),bin log 的主要功能就是归档和主备份一致,在集群的架构中,用于集群中各个实例间数据传输的日志就是 bin log,bin log 主要有三种格式  row, statement, mixed格式。

row:日志中会记录成每一行数据被修改的形式。

statement:数据操作的 sql。

mixed:根据需要自动判断是使用 row 还是 statement,例如如果 是  insert 或 deleted 语句就使用 row 进行记录。


Mysql 原理详解(一):日志索引事务篇

    大老师提问

为什么一个数据操作要使用两套日志系统记录呢?

两阶段提交

通过两个日志的配合实现双阶段提交,为了让两个日志的逻辑保持一致,可以更好的从cash 中恢复数据。

恢复的备份库,是通过 备份数据 + bin log 重放的方式去恢复数据的,从 cash 中恢复的数据库是从 redo log 中恢复数据的,所以,不管是先写 redo log 还是 bin log 都会造成恢复数据和 cash 数据不一致的情况,所以必须使用 两阶段提交,保证日志逻辑的一致性。

redo log 和 bin log 一个也不能少

mysql 在一开始使用的是 myisam 不是现在的 innodb ,这个数据库是没有 safe-cash 的能力的,而 innodb 为了弥补添加了 redo log,那只用 redo log 不使用 bin log 可以吗?也是不行的,因为 bin log 有其独有的数据归档能力,如果没有 bin log 就不会有mysql 集群,不会有读写分离等技术了。


02

Mysql-索引篇

什么是索引?

(数据库术语)在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。

索引的常见模型

Hash 模型 (只能进行等值查询)

数组模型(插入操作的时间复杂度太高)

二叉搜索树模型(内存IO消耗太大)

Mysql 原理详解(一):日志索引事务篇

Mysql的索引类型:B+树索引模型

mysql 中的索引是使用 B+ 树,整体的结构就像是下边这棵树,树的查询的时间复杂度是 O(nlogn),查询效率很高,但为啥不是B树呢?底层数据存储结构决定的。

B 树和 B+ 树的区别:B 树的所有节点都指向数据的指针,B+ 树的只有所有的叶子节点带有指向数据的指针。

Mysql 原理详解(一):日志索引事务篇
Mysql 原理详解(一):日志索引事务篇

主键索引和普通索引

ID 对应的索引结构是主键索引,K对应的是普通索引,从图中不难看出,主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index);非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。

Mysql 原理详解(一):日志索引事务篇

                                                                           大老师再提问   

一条查询 sql 是如何利用索引进行查询的呢?

Mysql 原理详解(一):日志索引事务篇

先了解一个名词回表,从普通索引上找到某个匹配的目标值,然后拿到关联的主键 id,去主键索引上获取记录完整数据的过程叫做回表。

例如 select * from t where k = 3 的执行流程:通过索引 K 匹配到 k = 300,然后再去到主键索引上拿到数据 R3 返回给客户端。也就是一次回表,在这个过程中读了索引树 k 一次,回表一次。

索引的常见优化手段

联合索引

由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。当然维护索引是需要付出代价的,如果将很多字段都放在索引上,维护代价巨大还会消耗很大的空间,因此,在建立冗余索引来支持覆盖索引时就需要权衡考虑了。

最左前缀匹配原则

select * from t where name like “张%”;此时 sql 的执行流程又是怎样的呢?

如果你要第一个字是“张” 的,查找到第一个符合条件的记录是 ID3,然后向后遍历,直到不满足条件为止。他也能用上这个索引,进行最左前缀的匹配。所以,在建立联合索引的时候,如何安排索引内的字段顺序?能通过调整联合索引字段顺序能少维护索引,那就是最好的。其次就是考虑空间。

索引下推

select * from t where name like “张%” and age = 30; 这个索引的执行流程又是怎么样的?

在 mysql 5.6 之前,只能取出满足 “张%” 的记录然后开始回表,但是在 mysql 5.6 中引入了索引下推,也就是说,可以通过联合索引上的条件直接判断,直接过滤掉不符合条件的记录,减少回表次数。


03

Mysql-事务篇

mysql 的事务是在引擎层实现的,mysql 原生的 myisam 引擎是不支持事务的,但是 mysql 是一个支持多引擎的系统,我们今天使用的 mysql 的事务是由 innodb 提供的,这也是 myisam 被 innodb取代的一个重要原因。


事务的特性和隔离级别

特性:原子性,一致性,隔离性,持久性。(ACID)

隔离级别:读未提交,读提交,可重复度,串行化。



让我们开启一个事务

我们向系统申请了一个 transaction id = 100,系统还顺带告诉了你 现在活跃的事务(还没有提交的事务),所以呢,你可以得到下图:

低水位:当前活跃的 transaction id 的最小值

高水位:当前活跃的 transation id 的最大值,可能是自己也有可能不是。

当我们拿到这个数组,其他数据的可见性规则,是怎么样的呢?

数据的 trx_id 落在绿色部分,trx_id < 低水位 说明在我们的事务事务开启前,这个数据就已经提交了,该版本数据对我们可见。


数据的 trx_id 落在红色部分,trx_id > 高水位说明在我们的事务事务开启后,这个数据版本的事务还没开启,该版本数据对我们可见。


数据的 trx_id 落在黄色部分 低水位 <= trx_id <= 高水位。

trx_id 在数组中,当前事务创建时候,trx_id 未提交,不可见。

trx_id 在不数组中,当前事务创建时候,trx_id 已经提交,可见。

通过以上操作,innodb 拥有了秒级别创造快照的能力 !



Ok~至此mysql原理详解第一部分已经全部分享完成,敬请期待第二篇: mysql原理详解(二)-内存与锁篇





Maliao

码里遨


● 感谢关注 ●