通俗易懂-mysql事务持久化实现
硬盘
目前主流的有2种,一种是机械硬盘,一种是固态硬盘
大家知道,固态
mysql是基于硬盘的数据库,所以很多优化都是基于硬盘的瓶颈来做的,为了更好的理解,先花点时间了回忆下硬盘的知识 硬盘 目前主流的有2种,一种是机械硬盘,一种是固态硬盘 大家知道,固态硬盘读写速度比机械硬盘块,而且快很多,那么快的原因是什么呢? 主要跟他们的构造和工作原理有关 机械硬盘结构 机械硬盘主要由,转抽,磁头,盘片组成,一个盘片上划分了很多个磁道,每个磁道上又进一步分了扇区 其中扇区是实际存储数据的地方,一个扇区的大小是512个字节,当对机械硬盘进行读写时需要经过三个步骤 其中步骤1,2的定位操作都是机械定位 固态硬盘结构 固态硬盘主要有电路,闪存芯片组成,其中闪存芯片是实际存储数据的地方 对固态硬盘的读写分两步 其中步骤1的定位是电子定位 电子定位肯定比机械定位的速度要快,这也是固态硬盘读写速度快的主要原因 硬盘比较底层,写程序的时候也接触不到,我们更多是与文件系统打交道。 有人说过一句的名言:“计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决” 文件系统,对于硬盘和上层应用程序来说就是这个中间层,那么这个中间层解决了什么问题呢? 文件系统干了什么事? 主要就一个: 扇区变块 (默认:1block=8扇区=4K) 块这个概念我们很熟悉了,块是由多个连续组成 为什么要把扇区变为块呢? 假设一个要写1M的数据,直接操作扇区的块需要的写次数是 1024*1024/512=2048,意味转需要2048次的机械定位 如果操作块,需要写次数256次,直接提升了磁盘操作的效率,但是带来的就是磁盘碎片,磁盘碎片和效率比肯定效率更重要,毕竟磁盘的成本低 到此我们知道为什么不直接与硬盘打交道,额是与文件系统打交道的原因? 那么与文件系统打交道都有哪些方式的呢? 2种: 先看下随机读写是怎么操作的? 假设要创建一个7kb的数据文件 通过对读写过程的分析我们知道,随机读写模式,空间分配策略是按需分配,要多少就分配多少,但是分配的block之间不是连续,由于不是连续的,磁头需要频繁切换,这是随机读写模式的瓶颈 顺序读写是怎么操作的? 顺序读写解决了磁头频繁切换的问题,因为block是连续的 这种模式不常见因为要采用这种方式需要两个条件: 所以通过分析,我们平常写日志用的是随机读写模式,因为文件大小一般都是不固定的 如何印证下顺序读写和随机读写区别? 查看文件的存储地址
随机读写文件存储block地址 结论: 顺序读写block地址是连续,随机读写block地址是不连续的 顺序读写比随机读写快,那么到底快多少? 小结一下 操作系统如何保证上层应用程序对磁盘的读写性能? 不管是随机读写还是顺序读写都绕不开磁头机械操作, 那么对于多任务的操作系统,os如何保证上层应用程序对磁盘的读写性能? 性能不够缓存来凑 我们知道linux为了保证系统的安全,按照运行空间,分了内核空间和用户空间mysql持久化,文件系统运行在内核空间,上层应用程序运行在用户空间,为了提高文件的操作操作,上层应用并不直接操作磁盘,而且先写到文件buffer(一块内存),buffer的内容按照一定的策略异步刷新到磁盘,读的时候先读cache,cache读不到再去磁盘上读,这跟我们的用redis差不多,先读redis,读不到再去读库 文件的写入过程默认是异步的,又叫延迟写 buffer和cache使用情况 free –m 红框内就是buffer和cache 当系统内存不够时,系统的回收这部分内存,所以系统可用内存=total-used+buffer+cache 磁盘异步刷新策略是? 三种: 策略值可用命令修改 系统突然宕机,断电,数据一致性如何保证? 为了解决数据丢失问题,linux系统提供了fsync,fysnc的作用是直接将数据刷新到磁盘,下面两个代码段是写文件,一个是延迟写入,一个是实时写入 进入正题-mysql事务持久化实现 mysql实现事务的持久化面临哪些挑战? 数据库特点:高性能 持久化特点:磁盘瓶颈 高性能 与 持久化 存在矛盾 数据库选择了高性能 要高性能,毫无疑问在内存里面操作是性能最高的 所以Mysql对于数据的修改总是先修改内存中的数据,按照功能 划分为,数据buffer,索引buffer,锁buffer,relog等。。 事务具有四个特性: 我们看这个事务,很简单,一个金额加,一个金额减 首先修改在内存里面修改金额,因为要支持回滚,所以修改前的数据要放到一个地方存起来,这个地方就是undo log,就是右边绿色的部分,当执行回滚操作时,直接把undo log的覆盖回来就行 修改后,数据buffer的内容定期同步到磁盘,落地的路径: 数据buffer-》os bufer-》硬盘 一个问题: 修改数据之后,数据buffer直接刷到os buferr ,然后调用磁盘同步函数fsync,不就可以直接实现持久化吗? 是的,可以这么做,mysql为啥没有这么做,主要原因是数据buffer直接落地的过程磁盘是一个随机写的过程,事务持久化的目的是保证数据不丢,那换个角度想,如果丢了可以能够找回来是不是也行? 是的,mysql,就是按照这个思路来实现持久化的,叫做WAF技术=write ahead log(写前日志) 根据分析redo log还是要落地才能保证持久化,跟在数据buffer修改后,直接持久化有啥不同呢? 主要是2点: 所以mysql是否持久化的关键要看redo log的持久化策略,mysql提供了三种redo log持久化策略 所以数据使用哪种持久化方式要看应用具体场景 如何查询mysql 使用了持久化哪种策略? 由于redolog要实现顺序写,所以文件大小要是固定的 不同持久化方式的对mysql性能影响? 看一个例子
存储过程p_load的作用是将数据不断的插入test_load表中,并且每次插入就显示的就进行一次commit操作,在innodb_flush_log_at_trx_commit设置不同值时,调用存储过程记录插入10万行记录所需要的时间 innodb_flush_log_at_trx_commit=0 innodb_flush_log_at_trx_commit=1 innodb_flush_log_at_trx_commit=2; innodb_flush_log_at_trx_commit1万行插入耗时 0 0.67s 1 13.93s 2 0.93s 性能结果跟我们预期的一样,0最好,1最差,2中间 总结 (编辑:青岛站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |