Mysql - 日志相关问题

打印 上一主题 下一主题

主题 989|帖子 989|积分 2967

通过一些问题来讨论 Mysql 中的日志:


  • Mysql 是怎么包管原子性的?
  • Mysql 怎么包管长期性的?
  • Mysql 怎么包管隔离性的?
  • 先容一下 binlog 和 redo log,他们两有啥区别?
  • 两阶段提交相识吗?先容一下,为啥必要两阶段提交呢?
  • 幻读相识吗?先容一下,innodb引擎是怎样办理幻读问题等?
  • 刚才我们说到了原子性,那宕机时还能包管原子性吗?undolog在宕机是怎么包管原子性的?


1. Mysql 是怎么包管原子性的
原子性是说,事件中的操纵,要不一起执行完成,要不一起失败回滚
Mysql 主要是使用 undo log,也就是回滚日志来实现原子性
平常我们在对数据举行增删改时,InnoDB 除了会记录 redo log,还会将更新的数据记录写进 undo log 中。当事件出现非常,执行失败的时候,就可以使用 undo log 中的信息将数据回滚到修改之前的版本

2. Mysql 是怎么包管长期性的
长期性是指,一旦事件提交,它对数据库的改变就应该是永久性的,接下来的其他操纵或故障不能对其有影响。InnoDB 中主要是通过 redo log 来包管事件的长期性。其中还用到 WAL 技术
WAL 的关键点在于 Mysql 的写操纵并不是立刻写到磁盘上,而是先写日志,然后在符合的时间再写到磁盘上。具体来说,当有一条记录必要更新时,InnoDB 引擎会先把记录写到 redo log 里,并更新内存,这个时候整个记录的更新就算完成了。后续,InnoDB 引擎会在得当的时候,由背景线程将缓存在 Buffer Pool(缓存池) 里的脏页革新到磁盘里,这个时候每每也是体系空闲的时候
有了 redo log,当体系瓦解时,即使脏页的数据没有来得及长期化,但 redo log 已经长期化了,Mysql 就可以根据 redo log 记录的内容,将所有的数据恢复到最新状态,整个过程也就是常说的 crash - safe能力

3. Mysql 是怎么包管隔离性
隔离性是指一个事件内部的操纵以及操纵的数据对正在举行的其他事件是隔离的,并发执行的各个事件之间不能相互干扰。隔离性可以防止多个事件并发执行,可能存在交织执行导致数据的不同等。Mysql 对隔离性的包管主要有两个方面,用锁机制来包管一个事件写操纵对另一个事件写操纵的隔离性,用 MVCC(多版本并发控制)机制来包管一个事件写操纵对另一个事件读操纵的隔离性。
Mysql 中按锁的粒度,可以分为全局锁,表锁和行锁。全局锁会使整个数据库处于只读状态,在做全库逻辑备份时常常用到。表级锁在操纵数据时会锁定整张表,并发性能一样平常,而行锁可以做到只锁定必要操纵的记录行,并发性能很好。但是由于加锁自己必要消耗资源,因此某些锁定数据较多的情况下可以使用表锁来减少开销
MVCC 主要办理的是读写冲突的问题,它是由 undolog + read view 实现的。其中 undo log 可以为每条记录保持多个历史版本,Mysql 在执行快照读的适合,会根据事件的 read view 里的信息,顺着 undo log 的版本链找到满意可见性的记录

4. 先容一下 binlog 和 redo log,他们两有啥区别?
redo log 是 InnoDB 独有的,记录的是某个数据页做了什么修改,每执行一个事件就会产生相应的 redo log。当事件提交时,只需将 redo log 长期化到磁盘即可,可以暂时不考虑将 Buffer Pool 的脏页写回,而是在符合的时间交给背景线程去做。体系故障瓦解时,Mysql 也可以在重启之后使用 redo log 里的内容恢复数据
 
bin log 是 Server 层的日志,记录的是所有数据库表结构变动和表数据修改的日志。在 Mysql 完成一条更新操纵后,Server 层都会天生一条 binlog,在事件提交时,会将事件整个执行过程中产生的所有 bin log 统一写进 bin log 文件,主要用于 "归档"

两者的区别主要有四点,首先是实用对象不同,binlog 是在 Mysql 的 Server 层实现的,所有存储引擎都可以使用。而 redo log 是 InnoDB 引擎独有的;其次是文件格式不同,bin log 是逻辑格式,记录的是某个语句的原始逻辑,比如 "给 ID 为 1 的 A 字段加 1"。而 redo log 记录的是某个数据页上做的修改,比如 "某个表空间中的某个数据页的某个偏移量处做了什么更新" ; 尚有写入方式不同,bin log是追加写,写满一个文件就在创建一个新文件继续写。而 redo log 是循环写,日志空间的大小是固定的,写满就必要先刷脏页,然后继续从头写

5. 两阶段提交相识吗?先容一下,为啥必要两阶段提交呢?
两阶段提交在 Mysql 中主要用来确保  redo_log 和 bin_log 在逻辑上保持同等
具体的,在 Mysql 中执行一条更新语句时,在语句执行的最后必要分别写 redo log 和bin log。Mysql 把整个过程分为两个部分:首先先写 redo log,并把它标为 prepare 状态,然后紧接着写 bin log,等到 bin log 写完之后再将 redo log 标志为 commit 状态。这样的话,无论写日志的过程中 redo log 和 bin log 哪个环节出现问题,在瓦解恢复时都会包管两个日志体系的数据同等性
比如,假设写 redo log 处于 prepare 阶段之后,写 bin log 之前发生了瓦解,由于此时 bin log 还没有写,redo log 还没有提交,瓦解恢复时整个事件就会回滚。再假设 bin log 写完了,但 redo log 还没 commit 就瓦解了,这时在瓦解恢复时体系会判定 bin log 是否是完整的,如果完整,则提交事件,不完整则回滚事件
着实两阶段提交不仅存在于 Mysql 中,它还是分布式体系中用于包管事件同等性的协议。关键在于必要包管提交阶段所有参与者的操纵要么都提交成功,要么都回滚

6. 幻读相识吗?先容一下,innodb引擎是怎样办理幻读问题等?
幻读是指一个事件在前后两次使用当前读查询同一个范围的时候,后一次的查询看到了前一次查询没有看到的新插入的行。必要留意的是,在 RR(可重复读)隔离级别下的普通查询是快照读,使用 MVCC(多版本并发控制)确保了别的事件不好插入数据,所以幻读在 "当前读" 下才会出现
幻读会带来两个问题,首先是会破坏给目的行加锁的语义,导致出现新的目的行被修改;其次是会导致数据和日志在逻辑上的不同等,即使把所有的记录都加上锁,还是可能会被其他事件插入新的记录
InnoDB 为了办理幻读,引入了间隙锁,这样在使用 select ... for update 语句时,会在对目的行加锁的同时,不仅加了行锁,还给两边的间隙页加上了间隙锁,这些就确保了无法再插入新的记录,同时已存在的数据页不能更新成间隙内的数据,也就不会出现幻读情况
不外也有一些特殊情况,比如事件 A 在 T1 时刻举行快照读,事件 B 在 T2 时刻插入记录,事件 A 在 T3 时刻举行当前读,此时会查失事件 B 新增的记录,也就出现了幻读。为了制止这类特殊场景下的幻读,最好是在事件开启之后,立马执行 select ... for update 这类当前读语句

7. 刚才我们说到了原子性,那宕机时还能包管原子性吗?undolog在宕机是怎么包管原子性的?
可以的,由于每个事件执行时,在提交事件前都会将对数据的修改记录到 undo log 中,现在假设 Mysql 正在执行某个事件时突然宕机,假云云时事件还没有提交,那么恢复时体系会通过 undo log 依次对数据举行相反操纵,比如已经 insert 了一条记录,那么就 delete 这条记录等等,对这个未完成的事件举行回滚,确保事件的原子性;如果宕机前事件已经提交了,那么事件就无需回滚,齐备正常


诚恳欢迎各人提出意见Orz
......(待续未完




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表