在使用 Mysql 集群时,通常master节点负责写操作,slave节点负责读操作。主节点写入的数据同步到从节点的具体实现是:
mysql使⽤3个线程来执⾏复制功能(其中1个在主服务器上,另两个在从服务器上)。当发出start slave时,从服务器创建⼀个I/O线程,以连接主服务器并让它发送记录在其⼆进制⽇志中的语句。主服务器创建⼀个线程将⼆进制⽇志中的内容发送到从服务器,也就是Binlog Dump线程。从服务器I/O线程读取主服务器Binlog Dump线程发送的内容并将该数据拷⻉到从服务器数据⽬录中的本地⽂件中(中继⽇志)。第3个线程是sql线程,由从服务器创建,⽤于读取中继⽇志并执⾏⽇志中包含的更新。在从服务器上,读取和执⾏更新语句被分成两个独⽴的任务。当从服务器启动时,其I/O线程可以很快地从主服务器索取所有⼆进制⽇志内容。
binlog 记录了对数据库执⾏更改的所有的写操作,包括所有对数据库的数据、表结构、索引等等变更的操作。
redo-log是属于引擎层(innodb)的⽇志,称为重做⽇志,当MySQL服务器意外崩溃或者宕机后,保证已经提交的事务持久化到磁盘中(持久性)。它能保证对于已经 COMMIT 的事务产⽣的数据变更,即使是系统宕机崩溃也可以通过它来进⾏数据重做,达到数据的持久性,⼀旦事务成功提交后,不会因为异常、宕机⽽造成数据错误或丢失。
为什么有了binlog还要有redo-log?这是因为MySQL 是以⻚为单位进⾏刷盘的,每⼀⻚的数据单位为16K,所以在刷盘的过程中需要把数据刷新到磁盘的多个扇区中去。⽽把16K数据刷到磁盘的每个扇区⾥这个过程是⽆法保证原⼦性的,如果数据库宕机,那么就可能会造成⼀部分数据成功,另⼀部分数据失败的情况。⽽通过 binlog 这种级别的⽇志是⽆法恢复的,因为⼀个update可能更改了多个磁盘区域的数据,所以这个时候得需要通过redo log这种记录到磁盘数据级别的⽇志进⾏数据恢复。总的来说:
MySQL 将redo log的写⼊操作拆成了两个步骤prepare和commit进⾏,在事务执⾏期间,写⼊的redo log标记为prepare阶段,待事务提交且bin log写⼊成功时,才将redo log标记为commit阶段。具体流程如图:
下⾯具体分析写⼊log时发⽣异常的情况:
多版本并发控制全称Multi-Version Concurrency Control,是⼀种并发控制的⽅法,⼀般在数据库管理系统中,实现对数据库的并发访问。MVCC 在 MySQL InnoDB 中的实现主要是为了提⾼数据库并发性能,⽤更好的⽅式去处理读-写冲突,做到即使有读写冲突时,也能做到不加锁,能够⾮阻塞并发读取。
在了解 MVCC 之前,需要先区分两个概念:当前读和快照读。MySQL 在读取数据时,可以分为当前读和快照读两种形式。
有了这个基础后,就可以继续探讨 MVCC 的具体实现了。
MVCC 主要是通过 undo_log 多版本链条,加上开启事务时产⽣的 readView(不同隔离级别有不同产⽣策略)来实现的。当查询的时候,根据 readView 进⾏判断,来决定读取哪个版本的数据。
在 MySQL 中,每个数据⾏都有⼀个版本链,包含了该数据⾏的所有历史版本。每次更新操作都会⽣成⼀个新的数据版本,⽽不是覆盖旧版本。这些版本按照时间顺序连接在⼀起,形成版本链。下图是undo log的主要结构。
在insert的时候,undo log只在回滚的时候需要,在事务提交后可以⽴即删除,不需要记录上⼀个版本该⾏的数据(因为上⼀版本该⾏不存在);在 update 和 delete 的时候,不仅回滚的时候需要,多版本并发控制的时候也需要⽤来记录上⼀数据版本,因此事务提交后也不会⽴即删除。
当⼀个事务开始时,它会创建⼀个读视图(Read View)。ReadView 其实就是一个保存事务ID的列表。记录的是本事务执行时,MySQL 还有哪些事务在执行,且还没有提交。读视图主要包括以下信息:
版本链数据的访问规则主要依赖于undo log记录的当前事务的id,即隐藏字段 DB_TRX_ID,⽤这个id去匹配下⾯的规则,如果符合其中某⼀条件,说明当前版本是可以读取的;如果不符合条件,说明这个版本的数据不能读,就会顺着版本链去寻找更⽼的版本的数据
在不同隔离级别下,readview ⽣成的时机不同。
所以MVCC可以解决不可重复读问题,但是不能解决幻读问题。幻读只能通过范围锁(Range Locking)来解决。范围锁允许事务锁定⼀定范围的数据,以确保其他事务不能在这个范围内插⼊新数据或修改已有数据。因为事务可以锁定整个范围,从⽽保持了数据的⼀致性。例如,在⼀个订单表中,如果⼀个事务正在检查某个时间范围内的所有订单,并且希望防⽌其他事务在这个范围内插⼊新订单,就可以使⽤范围锁来锁定这个时间范围。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。