目录
下面几种情况会flush(flush的时候 我们的mysql可能会抖一下)
概述
简单介绍 下mysql常用的恢复数据两个日志文件redolog(innodb特有)和binlog(server层特有)
mysql的wal就是写入redolog的
差异
redolog | binlog | |
归属 | innoDb引擎特有 | server层-公用 |
文件写入方式 | 循环写入几个文件(会覆盖),通过writePos和checkPoint释放空间 持续写入 | 追加写入,可以理解成一直写 |
写入内容 | 物理:记录了数据页上做的修改 | 逻辑:有语义的,比如给某个字段值+5 |
关联协作(如何保持一致,两阶段提交)
以sql执行为例(更新一条记录 update t set x = 1 where id = 1)
1.执行器找引擎要id=1的记录(引擎用树搜索这条记录,先找加载的内存页中有没有,没有就去磁盘加载到内存)
2.执行器更新数据,调用引擎的写入接口
3.引擎将数据写入内存,同时内存中写入redolog(prepare状态)告知执行器现在是执行完成 随时可以执行事务提交
4.执行器记录binlog 写入磁盘
5.执行器调用引擎提交事务接口,引擎将redolog变成commit状态,完成更新
具体关联是通过一个字段xid,redolog和binlog都有一个xid的字段
异常场景
步骤5的时候,数据库挂了 咋搞?
scene1:
如果redolog里面有commit标示 直接提交事务
scene2:
如果redolog此时是prepare,会判断下binlog是否完整,如果完整,提交事务,否则回滚
(这里一个细节,binlog完整就可以提交事务,因为这样从binlog恢复数据就不会丢数据)
binlog
日志格式
statement
记录的是原始的语句,走的索引可能有偏差(主库用的索引A 备库用的索引B 影响的行会不一样),容易造成主备不一致。【所以不要用这个】
分享一个血淋淋的案例
我们以前有一个月批发券的活动,每个月两千万条左右的记录。
sql是没有加hint的,到第12个月的时候 报了longSql,联系DBA查看是索引走偏了
(被数据库的优化器”优化了“)
row
记录的信息太多,文件大小太大,比如删除N条记录,会记录N行 每行都会唯一定位到主键,但是推荐使用
mixed
结合上述两种,如果有可能会出现主备不一致 就使用row,其他使用statement
flush
mysql操作比较快很大一部分原因是直接操作的内存,【buffer Pool(里面包含一些加载到内存中的数据页和changeBuffer)】,加上wal顺序写redolog
当内存中的数据页和磁盘中的数据不一致,这个就是脏页。
下面几种情况会flush(flush的时候 我们的mysql可能会抖一下)
1.bufferPool的容量不够了(系统内存不足,无法产生新的内存页,淘汰一些脏页)
一个查写如果捞的数据页特别多,会淘汰很多脏页的话,脏页需要刷新到磁盘,这个操作会很慢。 要控制好脏页的比例(innodb_max_dirty_pages_pct)默认是75%
2.redolog文件写满了(把checkpoint往前推,推移的部分写到磁盘) 【这个时候就会像java的stw一样,系统不会再接受更新】
3.mysql认为db处于空闲状态了(负荷比较小)
4.mysql关闭