MySQL入门教程(10)存储引擎、Redo log、Undo log

Tanglu MySQL 2022-12-06 1410 0

一、MySQL常用存储引擎

存储引擎可以理解为是数据库自己的文件系统,不同类型的存储引擎有不同的特点。存储引擎位于表级别,也就是说可以为每张表设置不同的存储引擎进行使用。常见的存储引擎有MyISAM、InnoDB、Memory、TokuDB、CSV等:

· MEMROY:数据存放在内存中,速度非常快,但是不进行持久化处理,如果数据库重启或者崩溃,只会保存表结构(因为有.frm文件),数据会丢失,适用于存储临时数据

· CSV:数据以文本形式进行存放,可以直接编辑,但是由于不支持索引,所以不适合OLTP应用(因为所有SQL都是全表扫描)

· TokuDB:压缩比可以达到25倍,对数据的插入和删除速度也很快。适用于有大量插入或者删除操作的场景,如Zabbix

· Archive:数据使用zlib压缩存放,适合于存储归档数据,如日志信息。只支持INSERT和SELECT操作,插入速度快,不支持索引,查询性能差

· MyISAM:MySQL 5.5.5之前默认的存储引擎。数据存放在.frm、.MYD、.MYI三种类型的文件中,可以直接拷贝表文件到其他数据库中进行使用。由于是表级锁、不支持行锁、不支持热备、不支持事务等原因已经少使用

· InnoDB:MySQL 5.5版本以后默认的存储引擎。支持MVCC(多版本并发控制)、群集索引(聚簇索引)、事务、行级锁、热备。数据存放在.frm、.ibd两种类型的文件中,5.6开始默认会开启独立表空间,每张表都会有一个独立.ibd文件。InnoDB存储结构为表空间、段、区、页、行。一页默认16K,一个区默认为1M,所以一个区里面默认是有64个页。由于InnoDB还依赖共享表空间文件ibdata1存放undo log,以及ib_logfile存放redo log,所以不能直接拷贝.ibd到其他数据库进行使用

show engines  #查看当前MySQL所支持与默认的存储引擎
set global default_storage_engine=innodb  #在线修改全局配置

#写入到配置文件中的配置
[mysqld]
default_storage_engine=innodb


二、Redo Log(事务重做日志)

1、Redo Log日志写入时机

Redo Log是InnoDB引擎独有的物理级别日志,用于记录数据页上所做的修改,用来确保事务的持久性。MySQL进行数据更新的时候会先修改buffer pool缓存、然后修改undo log、redo log buffer。当提交事务的时候一定会把redo log、binlog刷盘,最后完成redo log中的事务commit标记;最后IO线程把脏数据刷入磁盘。Redo Log和Binlog的区别在于后者是逻辑日志,而且写入的时间是不同的。MySQL为了保证两份日志逻辑上的一致,事务需要进行两阶段提交,顺序如下:事务更新数据 > 写入Redo Log(prepare阶段) > 事务写入Binlog > Redo Log设置(commit阶段)。即两个日志都要同时写入,这样就可以避免因为某个日志没有写入而导致数据在恢复后产生不一致的情况。Binlog是事务完成后才会写入,而Redo Log是在事务执行的时候同时写入,也就是说在Binlog之前就已经开始


2、Redo Log为什么高效

InnoDB会先基于Write-Ahead Logging(WAL)日志先行机制将这些更新记录按照顺序IO写的方式记录到一块内存空间中,这块空间叫做Redo Log Buffer(此时BUFFER区域存储的数据和磁盘页上还不一致,也叫做脏页)。当事务Commit时会把Buffer中的数据采用追加写的方式刷新到Redo Log File中(该文件保存于数据库的data目录下,以ib_logfile进行命名),等事务刷新到Log File后内存和磁盘中的数据就可以保持一致了。脏页刷新的时机取决于数据库innodb_flush_log_at_trx_commit的配置(如果发现原本很快的数据库突然慢了一下,有可能就是在刷脏页)

innodb_flush_log_at_trx_commit=0:不主动将redolog buffer刷新到Redo Log File中,而是依靠Innodb每秒刷新到磁盘,存在丢失一秒数据的风险

innodb_flush_log_at_trx_commit=1:每次事务提交时都将redolog buffer刷新到Redo Log File中

innodb_flush_log_at_trx_commit=2:每次事务提交时都将redolog buffer刷新到系统缓存中,然后由系统决定落盘时间,只有系统宕机时候会有丢失数据的风险


3、Redo Log为什么保证数据安全

如果事务在执行完成后数据库崩溃,在重启数据库之后MySQL可以通过redo log将已经提交的事务重新写到数据文件,保证事务不丢失。如果在写binlog之前数据库崩溃,此刻数据状态不满足两阶段提交,事务会被回滚,此时binlog还没写入,也不会传到从库。如果是在写入binlog后发生崩溃,那么则可以根据日志自动恢复数据(这也是为什么强烈建议配置双1参数的原因,保证了数据的安全


4、Redo Log什么时候进行刷脏

· 当Redo log写满时,系统会停止数据库所有更新操作,开始flush内存数据到磁盘,flush完成后Redo log继续滚动写入。此刻flush操作会让所有更新都阻塞,如果有监控的话,更新数基本为0

· 当系统内存不太够但又出现一个查询操作需要申请内存时也会触发flush操作。此刻如果需要淘汰的脏页太多也会影响服务性能。通常将innodb_io_capacity这个参数设置成磁盘的IOPS实现优化(磁盘的 IOPS 可以通过 fio 工具测试)

· 当MySQL空闲时自动flush,默认每秒一次

· 停止MySQL服务时会自动flush内存中的数据到磁盘


5、Redo Log参数配置项

innodb_flush_log_at_trx_commit=1 #redolog写入策略,双1参数之一
innodb_log_file_size=6G  #设置redo log文件大小,文件会自动命名为ib_logfile0~ib_logfileN,如果设置太小会导致数据库因为经常flush而间歇性性能下降
innodb_log_files_in_group=2  #设置redo log文件个数
innodb_log_group_home_dir=./  #设置redo log文件路径
# innodb_io_capacity=2000 #设置脏页刷新速度,单位为页。磁盘速度越快就设置越大,建议和磁盘IOPS一样
# innodb_flush_neighbors=0  #刷脏页时是否把数据页旁边的脏页也刷掉,1为一起刷,SSD磁盘建议为0,8.0开始默认为0


三、Undo Log(事务回滚日志)

1、Undo Log作用

Undo Log是一种逻辑日志,记录了事务在更新前的状态,确保了事务的原子性和一致性。Undo log会写入到ibdata和ibtmp文件中。当数据库重启进行crash-recovery时会通过Redo log将已经提交事务的更改写到数据文件,而还没有提交的就通过Undo log进行roll back。

Undo Log是MVCC实现的基础,MySQL通过Undo Log中存放的数据历史版本(有点像SVN)可以反向推算出数据之前的状态。这也是为什么在RC读已提交的隔离级别下用户还可以SELECT到历史数据的原因,因为读取到的是数据快照版本。MVCC的操作流程大概如下:获取事务自身的版本号,也就是事务ID > 获取历史版本视图(Readview) > 将查询得到的数据和视图种的版本号进行对比 > 如果不符合Readview规则就从Undo log种获取历史快照。


2、 Undo Log相关参数配置

innodb_data_home_dir = /data/mysql/  #共享表空间文件存放路径,文件名为ibdata1
innodb_data_file_path 	= ibdata1:1024M:autoextend  #共享表空间文件大小,可以写多个文件进行拆分
innodb_undo_tablespaces			= 4   #undolog独立表空间个数,默认为0,表示不为undolog设置独立表空间,而是记录到ibdata文件中。如果设置为4则代表创建命名为undo001~undo004的undolog。该配置在mysql初始化后就无法进行修改。
innodb_max_undo_log_size		= 1G  #单个回滚日志最大占用空间大小,默认为10M
innodb_undo_logs 	 			= 128 
innodb_undo_log_truncate		= 1   #当undolog超过innodb_max_undo_log_size阀值时对undolog空间进行收缩到10M

评论