JAVA全系列 教程
3762个小节阅读:7093.2k
目录
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
MySQL的事务实现离不开Redo Log和Undo Log。从某种程度上说,事务的隔离性是由锁和MVCC机制实现的,原子性和持久性是由Redo Log实现的,一致性是由Undo Log实现的。
redo log叫做重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者在磁盘中。当事务提交之后会把所有修改信息都会存到该日志中。
注意:
先写日志,再写磁盘的技术就是
MySQL
里经常说到的WAL(Write-Ahead Logging)
技术。
在计算机操作系统中,用户空间( user space
)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间( kernel space
)缓冲区( OS Buffer
)。因此, redo log buffer
写入 redo log file
实际上是先写入 OS Buffer
,然后再通过系统调用 fsync()
将其刷到 redo log file
中。
mysql
支持三种将 redo log buffer
写入 redo log file
的时机。innodb_flush_log_at_trx_commit。
参数值 | 含义 |
---|---|
0(延迟写) | 事务提交时不会将 redo log buffer 中日志写入到 os buffer ,而是每秒写入 os buffer 并调用 fsync() 写入到 redo log file 中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。 |
1(实时写,实时刷) | 事务每次提交都会将 redo log buffer 中的日志写入 os buffer 并调用 fsync() 刷到 redo log file 中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。 |
2(实时写,延迟刷) | 每次提交都仅写入到 os buffer ,然后是每秒调用 fsync() 将 os buffer 中的日志写入到 redo log file 。 |
不同的Redo Log刷盘规则,对MySQL数据库性能的影响也不同。
xxxxxxxxxx
create database if not exists test;
create table flush_disk_test(
id int not null auto_increment,
name varchar(20),
primary key(id)
)engine=InnoDB;
为了测试方便,这里创建一个名为insert_data的存储过程,接收一个int类型的参数。这个参数表示向flush_disk_test数据表中插入的记录行数。
xxxxxxxxxx
drop procedure if exists insert_data;
-- 该段命令是否已经结束了,mysql是否可以执行了。
delimiter $$
create procedure insert_data(i int)
begin
-- 声明变量 s
declare s int default 1;
-- 声明变量 c
declare c varchar(50) default 'binghe';
-- while循环
while s<=i do
-- 开启事务
start transaction;
-- 添加数据
insert into flush_disk_test (name) values(c);
-- 提交事务
commit;
-- s变量累加
set s=s+1;
-- 循环结束
end while;
end$$
-- 该段命令是否已经结束了,mysql是否可以执行了。
delimiter ;
查看刷盘规则
xxxxxxxxxx
show variables like 'innodb_flush_log_at_trx_commit';
将innodb_flush_log_at_trx_commit变量的值设置为0。
xxxxxxxxxx
set global innodb_flush_log_at_trx_commit=0;
调用insert_data向flush_disk_test数据表中插入10万条数据,如下所示。
xxxxxxxxxx
mysql> call insert_data (100000);
Query OK, 0 rows affected (2.18 sec)
注意:
可以看到,当innodb_flush_log_at_trx_commit变量的值设置为0时,向表中插入10万条数据耗时2.18s。
将innodb_flush_log_at_trx_commit变量的值设置为1。
xxxxxxxxxx
set global innodb_flush_log_at_trx_commit=1;
调用insert_data向flush_disk_test数据表中插入10万条数据,如下所示。
xxxxxxxxxx
mysql> call insert_data (100000);
Query OK, 0 rows affected (16.18 sec)
注意:
可以看到,当innodb_flush_log_at_trx_commit变量的值设置为1时,向表中插入10万条数据耗时16.18s。
将innodb_flush_log_at_trx_commit变量的值设置为2。
xxxxxxxxxx
set global innodb_flush_log_at_trx_commit=2;
调用insert_data向flush_disk_test数据表中插入10万条数据,如下所示。
xxxxxxxxxx
mysql> call insert_data (100000);
Query OK, 0 rows affected (3.05 sec)
注意:
可以看到,当innodb_flush_log_at_trx_commit变量的值设置为2时,向表中插入10万条数据耗时3.05s。
注意:
当innodb_flush_log_at_trx_commit变量的值设置为0或者2时,插入10万条数据耗费的时间差别不是很大,但是与innodb_flush_log_at_trx_commit变量的值设置为1对比来看,耗时差别较大。需要注意的是,虽然将innodb_flush_log_at_trx_commit变量的值设置为0或者2时,插入数据的性能比较高,但是在系统发生故障时,可能会丢失1s的数据,而这1s内可能会产生大量的数据。也就是说,可能会造成大量数据丢失。
实时效果反馈
1.MySQL中Redo Log主要作用是_____。
A 恢复数据
B 撤销回退的日志
C 记录更新操作
D 以上都错误
2.MySQL技术中刷盘机制,先写日志,再写磁盘的技术就是____技术。。
A WAL
B CAS
C WAP
D 以上都错误
答案
1=>A 2=>A