事务的实现
事务的持久性
背景:事务的持久性的是在磁盘的慢性能的背景下的要求。磁盘的吞吐量在我们随机修改的情况下性能特别差
持久性要解决2个问题:一是磁盘io的性能问题,二磁盘随机写的性能问题。
innodb的实现方式
使用redo log来实现,redo log分2部分,一个是内存的buffer,一个磁盘的file,磁盘的file是ringbuffer的结构
(ringbuffer的结构是性能很高的数据结构,因为他的大小是固定的,插入删除的时候只需要移动游标,这样就
不需要更改存储结构,只要知道哪一部分是有效数据即可,所以性能很好)。持久性的要求是提交的事务,数据
必须持久化。
基本过程是:
1.当事务提交之后,不直接修改磁盘b+树,而是把修改保存在内存的buffer中
2.buffer顺序append到redo log file中,把内存的数据刷到磁盘
3.当redo log满了的时候,数据库回去把log的数据apply到最终的数据结构上。
以上就是write-ahead log方式的实现过程。
是怎么解决上面的问题的呢?
一不要让所有的sql去做磁盘io,减少io次数
二是尽量避免随机写,redo log的写入时磁盘append的方式,性能解决磁盘的理论速度。
Q&A
写入到log file的数据就算是持久化了,不管这时候是否宕机,都不会丢失数据,只是还没来得及apply到表结构上而已
,当数据库再次启动的时候回加载redo log ,并把数据apply到表结构上。
这里有一个问题,如果buffer还没来得及刷到磁盘上的时候,数据库宕机了,这时候数据岂不是丢了吗?
答案是对,就是会丢数据!
所以innodb提供了3种方式来自行权衡(只要修改参数值即可),1就是每次commit,都去刷buffer来保证数据不丢失,
但是性能会差;2就是把buffer刷到系统的pagecache,即使mysql挂了系统不挂也没事;3就是缓存buffer,定时刷磁盘
,默认1秒,性能好,但是会有丢数据的风险。所以自己根据机器的可靠性来权衡设置参数。
有问题咨询公众号