mysql 日志,首先记住一个mysql原则 : 日志先行。
下文总结:
- server层,binlog+relaylog 用于主从复制。但是会出现case-unsave。binlog是逻辑日志。
- 存储引擎层-innodb,redolog+undolog,解决buffer-pool数据不持久化,实现crash-safe。但是 redolog不具有像binlog一样归档的作用。redolog 是物理日志。
- redolog的两阶段提交,保证了redolog和binlog的数据一致性。
MySQL有两层,一层是Server层,一层是存储引擎层。
1.binary log 和 relay log。 它Server层的日志。
2.redo log 和 undo log。 它是InnoDB引擎特有的日志
binlog的一主一从复制,基本过程:
在 Master 与 Slave 之间实现整个主从复制的过程是由三个线程参与完成的。其中有两个线程(SQL 线程和 IO 线程)在 Slave 端,另外一个线程(IO 线程)在 Master 端。
- a.Master将数据改变记录到二进制日志(binary log)中
- b.Slave上面的IO线程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容
(日志文件名和日志文件存放位置就是在配置主从复制任务时执行change master命令时指定的) - c.Master接收到来自Slave的IO线程的请求后, Master 服务器上的 IO 线程根据 Slave服务器的 IO 线程请求的信息, 读取指定 binlog 日志文件指定位置之后的 binlog 日志信息,然后返回给 Slave 端的IO 线程。 返回的信息中除了 binlog 日志内容外, 还有本次返回日志内容后在 Master 服务器端的新的 binlog文件名以及在 binlog 中的下一个指定更新位置,也就是是下一次复制内容该从什么地方开始。
- d.当 Slave 服务器的 IO 线程获取来自 Master 服务器上 IO 线程发送的日志内容及日志文件和位置点后, 将 binlog日志内容依次写入到 Slave 端自身的 relay log(即中继日志)文件(mysql-relay-bin.xxxxxx)的最末端,并将新的 binlog 文件名和位置记录到 master-info 文件中, 以便下一次读取 Master 端新 binlog 日志时,能告诉 Master 服务器需要从新 binlog 日志的哪个文件哪个位置开始请求新的 binlog 日志内容。
- e.Slave 服务器端的 SQL 线程会实时检测本地 relay log 中新增加的日志内容, 然后及时的把 relay log文件中的内容解析成在 Master 端曾经执行的 SQL 语句的内容, 并在自身 Slave 服务器上按语句的顺序执行应用这些 SQL语句,同时把执行状态信息保存在 relay-log.info 文件,应用完毕后清理应用过的日志。
- f.经过了上面的过程,就可以确保在 Master 端和 Slave 端执行了同样的 SQL 语句。 当复制状态正常的情况下,Master端和 Slave 端的数据是完全一样的。
参看文章:https://segmentfault.com/a/1190000019373762
crash-safe 概念
slave crash-unsafe 的原因在于应用 binlog 和更新文件的非原子性。
也就是上文的第e步骤会有问题。
开始解释:
IO thread 的执行状态信息保存在 master.info 文件, SQL thread 的执行状态信息保存在 relay-log.info 文件。
下面出现这样一个场景:
SQL thread 已经应用 relay-log.01 的4个事务
trx1(pos:10)
trx2(pos:20)
trx3(pos:30)
trx4(pos:40)
但是 SQL thread 更新位点 (relay-log.01,30) 到 relay-log.info 文件中,突然系统崩溃了。slave 实例重启的时候 sql thread 会重复执行事务 trx4。这就是典型的crash-unsafe了。
crash-safe 的原理:
crash-safe 情况下 SQL_thread 的工作模式
SQL thread 执行事务和更新 mysql.slave_replay_log_info 的语句合并为同一个事务,由 MySQL 系统来保障事务的原子性。
绿色的代表实际业务的事务,蓝色的是开启 MySQL 执行的更新slave_replay_log_info 相关位点信息的 sql ,然后将这两个 sql 合并在一个事务中执行,利用 MySQL 事务机制和 InnoDB 表保障原子性。不会出现应用 binlog 和更新位点信息两个动作割裂导致不一致的问题。
buffer pool 概念 -- innodb存储引擎带的一个缓存池
用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因 为引入了这一中间层,数据库对内存的管理变得相对比较复杂。
---buffer pool是innodb存储引擎带的一个缓存池,查询数据的时候,它首先会从内存中查询,如果内存中存在的话,直接返回,从而提高查询响应时间。(功能)
---修改更新等操作会改变buffer pool的一些数据,通过LRU算法更新,将buffer pool的命中率维持在一个比较高的水平。 (内存管理)
---是怎么将buffer pool中的数据同步到磁盘。想想如果更新一次buffer pool就写一次磁盘,那这样子的效率和直接读写磁盘并没有提高多少,这里就需要设计出同步策略来解决这个问题。(redo.log,undo.log)
---引入buffer pool会导致更新的数据不会实时地将数据持久化到硬盘,当系统崩溃时,虽然buffer pool中的数据丢失,数据没有持久化。但是系统可以根据redo log的内容,将所有数据恢复到最新的状态。
---修改buffer pool的数据后,同时还要将此操作记录在事务日志中去,保证事物安全的。事务日志文件是InnoDB引擎申请连续物理空间的固定大小的一个文件,对日志文件的读写基本上是顺序读写,寻址操作甚少。(redo.log顺序读写,减少寻址操作)
---Myisam引擎有Key Cache:只缓存索引文件,数据文件的缓存交由操作系统本身来完成。而buffer pool存放各种数据的缓存,包括索引页和数据页。
参看文章:https://www.cnblogs.com/iamsu...
redo log
介绍:因为最开始MySQL里并没有InnoDB引擎。MySQL自带的引擎是MyISAM,但是MyISAM没有crash-safe的能力,binlog日志只能用于归档。
而InnoDB是另一个公司以插件形式引入MySQL的,既然只依靠binlog是没有crash-safe能力的,所以InnoDB使用另外一套日志系统——也就是redo log来实现crash-safe能力。
redo log是固定大小的,比如可以配置为一组4个文件,每个文件的大小是1GB,那么总共就可以记录4GB的操作。从头开始写,写到末尾就又回到开头循环写。所以redo log 不想binlog一样会有归档功能。
将redo log的写入拆成了两个步骤:prepare和commit,这就是"两阶段提交"。 两阶段提交主要解决 binlog 和 InnoDB redo log 的数据一致性的问题.
如下图: