复制 Replication 是 MySQL 数据库提供的一种高可用方案,也叫主从备份。Replication 分为以下 3 个步骤,主服务器 master 把数据更改记录到二进制日志 binlog 中。
从服务器 slave 把主服务器的 binlog 复制到自己的中继日志 replay log 中。
从服务器根据 replay log 把更改执行到自己的数据库上,实现最终一致。
具体的实现方式是在从服务器开启 2 个线程,IO 线程读取主服务器的 binlog , 并将其保存为relay log
SQL 线程执行中继日志
复制原理是全备份加上日志备份还原,主要难点在于复制的实时性。
因为主从服务器之间存在执行延时,所以复制是一种异步实时。
执行延时会重度影响复制效率,并影响从服务器与主服务器之间的数据差异程度。
复制可以实现一些重要的功能,比如,从服务器可以看作主服务器的历史,通过在从服务器保存快照的方式实现数据备份
可以设置从服务器为 Read-Only,实现读写分离
问题来了,
微服务 A 所连接的 MySQL 实现了读写分离。假设一个事务中同时包含了读写请求,此时读的请求走从库且写的请求走主库,本地事务无法控制跨多库情况。分布式事务是基于本地事务实现的,所以也会失效。
如何解决?
—— 主流的解决方案如阿里云给出的是读写分离仅对显式事务(即需要显式提交/回滚的事务)以外的读请求有效,写请求和显式事务中的读请求(包括只读事务)均在主实例中执行,不会被分流到只读实例。
从分布式事务中可以看出事务执行对于一个项目来说很重要。
本系列开始讲解 MySQL,并从数据库层面思考事务。
MySQL 由以下几部分组成,连接池组件
管理服务和工具组件
SQL 接口组件
查询分析器组件
优化器组件
缓冲(Cache)组件
插件式存储引擎
物理文件
MySQL 区别于其他数据库的最重要特性就是插件式表存储引擎。特别地,MySQL 开源,用户可以自己编写存储引擎。
存储引擎可分为,MySQL 官方存储引擎
第三方存储引擎
大名鼎鼎的 InnoDB 存储引擎,虽然之后被 Oracle 收购,但是最早是第三方存储引擎。
对存储引擎进行一些介绍,
InnoDB
在 MySQL 5.5.8 开始成为默认存储引擎。
InnoDB 支持外键、事务、行锁设计,后续版本增加了全文索引。
InnoDB 实现了多版本并发控制 Multi-Version Concurrency Control MVCC,实现了 SQL 标准的 4 种隔离级别,默认 REPEATABLE。
InnoDB 使用 next-key locking 策略避免幻读 phantom。
InnoDB 实现了插入缓冲、二次写、自适应哈希索引、预读等功能。
InnoDB 存储引擎采用了聚集的方式,表存储数据按主键顺序存放。
MyISAM
在 InnoDB 之前的 MySQL 默认的存储引擎。
MyISAM 不支持事务,表锁设计。
NDB
数据全部放在内存中。
Memory
默认使用哈希索引,而不是 B+ 树索引。
数据库与传统文件系统的最重大的区别就是事务,然而上面的确存在部分存储引擎不支持事务。MySQL 的开发者认为不是所有的任务都需要事务,所以存在不支持事务的数据库。
下面开始对 InnoDB 进行详细说明。
InnoDB 是第一个完整支持 ACID 事务的 MySQL 存储引擎。结构如下,
InnoDB 是多线程模型,内部存在多个后台线程,Master Thread,核心线程,负责缓冲池数据刷回磁盘
IO Thread,使用异步 IO 进行回调处理
Purge Thread,清洁线程 回收 UndoLog
Page Cleaner Thread,拆分 Master Thread 职能,负责脏页刷新回磁盘
InnoDB 的 Master Thread 具有最高级别的线程使用权。其主要工作是判断 IO 空闲则将脏页刷入磁盘,而磁盘的读写性能一向是流量瓶颈。
InnoDB 引入了内存缓冲池来提高性能。缓冲池中的数据按照页进行组织,页大小默认 16 KB,包含了数据页、索引页、undo 页、插入缓冲页等等。
内存对象中还存在,重做日志缓冲池,保存事务提供的重做日志。
额外内存池,类似与内存的租借空间,有点类似于新生代向老生代分配内存对象的情况。
回顾事务提交过程,如果不涉及磁盘的话,整体流程应该如下,提交 RedoLog
修改页数据。如果出现宕机,则根据 RedoLog 恢复日志。
实际情况下,缓冲池和 RedoLog 池不是无限的,必须要在某些时间点把数据写入到磁盘中才行。这个机制叫做 Checkpoint。
每到检查点,缓冲池中的新数据会马上刷回到磁盘。这个检查点包括 Master Thread 的定时调用,或重做日志缓冲池或者内存数据缓存达到某一个阈值,默认 75%。
检查点一般只会将部分脏页刷入,叫做 Fuzzy Checkpoint。数据库关闭时执行全脏页刷入,叫做 Shark Checkpoint。
InnoDB 对数据插入使用的 LRU Latest Recent Used 最近最少使用算法进行了优化。
最新数据只会插入在距离尾部 37% 的位置,也就是从尾部数起 3/8 左右。
这是因为数据库会遇到数据扫描、全局数据查找这种操作。如果将这种全局数据插在头部,就可能覆盖真正的热点数据。