前言

本文是笔者学习“林晓斌”老师的《MySQL实战45讲》过程中的,对知识点的总结归纳以及对问题的思考记录,课程18年11月就出了,当时连载形式,我就上班途中一边开车一边听,学的比较糙,时隔两年现在再回头仔细回顾总结下。《MySQL实战45讲》是极客时间的收费课程,价格几十块并不贵,但是绝对是一个好课程,笔者收益颇深,推荐大家阅读。

第一章《一条查询SQL是如何执行的》总结

在第一篇文章中,作者主要通过一条查询SQL是如何执行的为出发点,介绍了MySQL的组成部分,每个部分做哪些事:

名词解释

连接器:主要管理与客户端的连接,鉴权以及安全性的校验工作。

查询缓存:MySQL为了提高查询效率,可能会将热点数据放入内存中,以便下次查询直接从查询缓存中返回数据。

分析器:当缓存中没有命中,就会想通过分析器,对SQL进行语法分析,是否合法等。

优化器:主要工作就是查询动作的优化,比如是否走索引,选择哪一个索引等。

执行器:负责执行SQL的部分,通过接口与存储引擎交互,获取查询结果并返回。

存储引擎:负责MySQL的数据存储和提取,索引结构都是有存储引擎定义的,并且是可拔插式的,用户可以根据自己需求选择不同的存储引擎,主要有InnoDB和MyISMA,MySQL5.5.5之后默认使用的是InnoDB。

执行步骤

那么一条查询SQL时如何通过这些组件执行的呢?

1、首先客户端需要连接到MySQL服务端,这时就需要连接器来验证用户名和密码,建立TCP连接了。连接后如果连接长期处理空闲状态,连接器就会自动断开他,默认是8小时,可以通过wait_timeout设置。

2、连接成功后,客户端向MySQL发送执行命令,比如发送一条查询语句:SELECT * FROM user WHERE id = 1;首先MySQL会在查询缓存中看是否存在该条数据的缓存,如果有就直接返回。没有则进入下一步。其实查询缓存在8.0版本后就移除了,因为查询缓存会在更新时全部清空,所以对于更新频率较高的场景,查询缓存会变得费力不讨好了,也可以通过query_cash_type设置成DEMAND禁用查询缓存。

3、先经过分析器,对改条SQL进行语法分析,是否符合语法规范,是查询语句还是更新语句等,是需要对哪张表进行操作。

4、之后通过优化器,发现id是主键,可以使用主键索引。

5、通过执行器,执行该条SQL之前会先校验有没有执行权限,如果有,执行器会通过该表存储引擎提供的接口,存储引擎通过索引树找出id=1的数据后,MySQL返回给客户端。

第二章《一条更新SQL是如何执行的》总结

上一章我们通过查询流程了解了MySQL各模块的功能,其实更新时也查不多,只不过为了保证数据的可恢复性引入了两个日志:redo_log和bin_log。那么为什么需要有这两个日志呢?

redo_log

首先redo_log是innoDB引擎提供的。当有数据更新或者插入时,innoDB并不是直接持久到磁盘,而是先修改缓冲池中的数据,成功后直接返回成功,再选择“合适的时机”刷入磁盘中。

那么有的同学就会问了,那如果内存中的数据还没来及刷到磁盘就crash(宕机)了,数据不就是丢失了吗?

是的,为了解决这个问题,innoDB引入了redo_log来解决这个问题。

当有插入更新请求时,innoDB先将结果写入的redo_log日志文件中,再修改缓冲池数据页,最后再适当的时候刷新到磁盘。这样即使宕机时,也可以通过redo_log恢复丢失的数据,这就是所谓的WAL技术 write-ahead-logging。

redo log在innoDB中是固定大小的,由4个1G的文件组成,所以redo log 是循环写的。

可以把染色环装理解为由4个redo log 文件组成的。

checkpoint:当前数据擦除的位置,擦除前要把记录更新到数据文件。

write pos:当前记录的位置。

checkpoint与write pos之间就是空闲部分,可以持续往后写,当write pos追上checkpoint时,说明文件都没写满,如果继续写,就需要停下来擦除一些数据,把checkpoint继续往前移。

有了redo log,innoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。

这里做个扩展:当数据库写物理页时,如果宕机了,那么可能会导致物理页的一致性被破坏。

可能有人会说,重做日志不是可以恢复物理页吗?实际上是的,但是要求是在物理页一致的情况下。

也就是说,如果物理页完全是未写之前的状态,则可以用重做日志恢复。如果物理页已经完全写完了,那么也可以用重做日志恢复。但是如果物理页前面2K写了新的数据,但是后面2K还是旧的数据,则种情况下就无法使用重做日志恢复了。

这里的两次写就是保证了物理页的一致性,使得即使宕机,也可以用重做日志恢复。

在写物理页时,并不是直接写到真正的物理页上去,而是先写到一个临时页上去,临时页写完后,再写物理页。这样一来:

A. 如果写临时页时宕机了,物理页还是完全未写之前的状态,可以用重做日志恢复

B. 如果写物理页时宕机了,则可以使用临时页来恢复物理页

InnoDB中共享表空间中划了2M的空间,叫做double write,专门存放临时页。

InnoDB还从内存中划出了2M的缓存空间,叫做double write buffer,专门缓存临时页。

每次写物理页时,先写到double write buffer中,然后从double write buffer写到double write上去。最后再从double write buffer写到物理页上去。

bin_log

binlog是MySQL的server层提供的,是跨存储引擎的,做归档用的。因为没有crash-safa能力,所以innoDB自己引入了redolog。

这两种日志有以下三点不同。

1 . redolog是innoDB引擎特有的;binlogg是MySQL的Server 层实现的,所有引擎都可以使用。

2 . redolog是物理日志,记录的是“在某个数据页上做了什么修改”;binlogg是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID= 2这一行的c 字段加1 ”。

3 . redolog是循环写的,空间固定会用完;binlogg是可以追加写入的。“追加写”是指binlogg文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

更新语句的执行流程

1、当MySQL接收到一条更新语句时update user name="老王" where id =1;,除了上面查询的那些前期步骤,执行器调用存储引擎接口获取到id=1 的数据。

2、执行器获取数据后,先将name改为老王的数据,调用引擎接口,将数据写入到redolog中,并处于prepared状态。

3、redolog写完后,修改缓冲池的数据。并返回给执行器。

4、执行器获得结果后,记录到binlog中,并修改redolog该条记录改为commit状态,更新完成。

之所以分两次修改redolog是为了与binlog保证数据一致。

第三章《事务隔离》

事务基本概念

这章节没什么好说的,主要介绍了事务的特性,隔离级别以及事务的实现。

说到事务,大家都知道ACID,即原子性,一致性,隔离性,持久性。

多个事务操作同一数据,可能出现的问题:

脏读:一个事务读取到的另一个事务没有提交的数据。

不可重复读:在一个事务中两次读取同一数据结果不一致。

幻读:在一个事务中两次读取数据的数量不一致。

隔离级别

读未提交:可以读到另一个事务中没有提交的数据。

读已提交:可以读到另一个事务已提交的数据。

可重复读:在一个事务中,即使另一个事务已提交了,在本事务中多次读取数据都是跟事务启动时读取的一致的。

串行化:最高的隔离级别,对同一行数据,读会加读锁,写会加写锁,最安全但效率也最低。

事务的实现

在事务开启时,生成一张视图,在事务执行期间读取的数据都是基于这张视图的,这是静态的并不受其他事务影响。

本质上,在MySQL中,当数据发生更新时,都会生成一条回滚操作,通过回滚操作可以获得操作前的状态,在事务中,每次操作都会被记录,直至事务被提交,回滚段才会被清理。所以在未提交之前,都可以通过回滚日志undo log,逐步将数据恢复到事务开启前的状态。

在5.5版本之前,回滚日志是保存在ibdata文件中的,日志回滚段被清理,文件大小也不会变,所以日常开发中,我们应该尽量避免长事务,应该在长事务中会保留很老的视图。

MySQL深入研究--学习总结(1)的更多相关文章

  1. MySQL深入研究--学习总结(2)

    前言 接上文,继续学习后续章节. 第四章&第五章<深入浅出索引> 这两章节主要介绍的索引结构及其如何合理建立索引,但是我觉得讲的比较简单. 总结回顾下吧,其实在我之前的文章< ...

  2. MySQL深入研究--学习总结(5)

    前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第20章<幻读是什么,幻读有什么问题?> 先 ...

  3. MySQL深入研究--学习总结(3)

    前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第九章<普通索引和唯一索引,如何选择> 从查 ...

  4. MySQL深入研究--学习总结(4)

    前言 接上文,继续学习后续章节.细心的同学已经发现,我整理的并不一定是作者讲的内容,更多是结合自己的理解,加以阐述,所以建议结合原文一起理解. 第13章<为什么表数据删除一般,表文件大小不变?& ...

  5. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  6. 手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

  7. 13本热门书籍免费送!(Python、SpingBoot、Entity Framework、Ionic、MySQL、深度学习、小程序开发等)

    七月第一周,网易云社区联合清华大学出版社为大家送出13本数据分析以及移动开发的书籍(Python.SpingBoot.Entity Framework.Ionic.MySQL.深度学习.小程序开发等) ...

  8. MySQL 定时器EVENT学习

    原文:http://blog.csdn.net/lifuxiangcaohui/article/details/6583535 MySQL 定时器EVENT学习 MySQL从5.1开始支持event功 ...

  9. 《Mysql 公司职员学习篇》 第二章 小A的惊喜

          第二章 小A的惊喜  ---- 认识数据库 吃完饭后,小Y和小A回到了家里,并打开电脑开始学习Mysql. 小Y:"小A,你平时的Excell文件很多的情况下,怎么样存放Exce ...

随机推荐

  1. 最大子阵 DP or 前缀和orb暴力 能过

    在一个给定的n*m二维矩阵中求一个子矩阵元素和的最大值. 思路: 1:一个二维矩阵由两个点可以确定,枚举两个点,取子矩阵最大值. 2:在一维矩阵中,求一个序列的最大子段,利用 f[i]=max(f[i ...

  2. Educational Codeforces Round 87 (Rated for Div. 2)

    比赛链接:https://codeforces.com/contest/1354 A - Alarm Clock 题意 一个人要睡够 $a$ 分钟,一开始睡 $b$ 分钟后闹钟响铃,之后每次设置 $c ...

  3. 【bzoj 2038】 [2009国家集训队]小Z的袜子(算法效率--莫队分块算法 模版题)

    题意:小Z有N只袜子,有不同的颜色.他有M个提问,问从编号为[L,R]的袜子中随机选一双同色的袜子的概率,用最简分数表示. 解法:经典的莫队算法--无修改.不强制在线(可离线).状态转移可以一步完成. ...

  4. Educational Codeforces Round 97 (Rated for Div. 2) D. Minimal Height Tree (贪心)

    题意:有一个从根节点\(BFS\)得来的序列(每次\(bfs\)子节点的时候保证是升序放入队列的),现在让你还原树(没必要和之前相同),问能构造出的最小的树的深度. 题解:不看根节点,我们从第二个位置 ...

  5. Codeforces Round #529 (Div. 3) E. Almost Regular Bracket Sequence (思维,模拟栈)

    题意:给你一串括号,每次仅可以修改一个位置,问有多少位置仅修改一次后所有括号合法. 题解:我们用栈来将这串括号进行匹配,每成功匹配一对就将它们消去,因为题目要求仅修改一处使得所有括号合法,所以栈中最后 ...

  6. Nginx 版本回滚

    目录 参考信息 源码安装 nginx-1.14.2 版本升级 nginx-1.16.1 版本回滚 ①.对于软件的版本升级.添加官方模块.添加第三方模块,都需要用源码安装包重新生成(configure) ...

  7. docker的网络-单主机(三种原生网络)none、host、bridge

    docker的网络分为:单主机.跨主机 这篇先说:单主机 我们先说一下docker的原生网络模式 网络模式 简介 优点 使用场景 none 空网络,没有网络 此网络与外界隔离,安全度非常高 适合公司内 ...

  8. Leetcode 30 串联所有单词的子串 滑动窗口+map

    见注释.滑动窗口还是好用. class Solution { public: vector<int> findSubstring(string s, vector<string> ...

  9. springboot( 三)redis demo

    redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化.除此之外,Red ...

  10. 010. NET5_命令参数读取+配置多种读取

    上节课遗留问题:上节脚本启动后,CSS样式丢失问题 解决办法:a.拷贝丢失的wwwroot目录:b. 给UesStaticFiles类指定读取wwwroot目录 静态文件读取 Nuget引入:Micr ...