mysql性能优化-MVCC

思考一个问题

mysql性能优化-MVCC_第1张图片

 

MVCC是什么?

MVCC:Multiversion concurrency control (多版本并发控制)

解释:

并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理,以达到用来避免写操作的堵塞,从而引发读操作的并发问题。

 

mysql中MVCC逻辑流程-插入

mysql性能优化-MVCC_第2张图片

假如一张表user有三个字段id,name,age,MySQL会默认的给每行后面加上一些隐藏的列,跟mvcc相关的有两列:DB_TRX_ID(数据行的版本号:本行数据入库时的版本号),DB_ROLL_PT(删除版本号)。这两列的值怎么来呢?开启一个事务(整个InnoDB的引擎有一个事务管理的地方,即全局事务id,自增型的),给表中插入两条数据,此时数据行的版本号就是全局事务id。

 

mysql中MVCC逻辑流程-删除

mysql性能优化-MVCC_第3张图片

假如当前进行了很多次的事务操作,要删除其中一条数据,MySQL就会找到要删除的这条数据,并把它的删除版本号记录为当前的事务id号。

 

mysql中MVCC逻辑流程-修改

mysql性能优化-MVCC_第4张图片

先将命中行的数据行copy一份到新的数据行,新的数据行的版本号是当前事务的id,将原行数据的删除版本号的值设置为当前事务的id。

 

mysql中MVCC逻辑流程-查询

mysql性能优化-MVCC_第5张图片

要同时满足两条规则,一是查找数据行版本号早于当前事务版本的数据行,即行的系统版本号小于等于当前事务的系统版本号,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的,而是查找删除版本号要么是Null,要么大于当前事务版本号的记录,确保取出来的行记录在事务开启之前没有被删除。
解决不可重复读问题的不是mvcc,而是undo log和redo log。
 

mysql中mvcc版本控制案例

数据准备:

insert into teacher(name,age) value ('seven',18) ;

insert into teacher(name,age) value ('qing',20) ;

tx1:

begin;                                                   ----------1

select * from users;                               ----------2

commit;

 

tx2:

begin;                                                    ----------3

updat teacher set age=28 where id=1; ----------4

commit;

案例1

1,2,3,4,2

案例2

3,4,1,2

 

mvcc版本控制案例一

mysql性能优化-MVCC_第6张图片

mvcc版本控制案例二

mysql性能优化-MVCC_第7张图片

Undo log

Undo Log 是什么: undo意为取消,以撤销操作为目的,返回指定某个状态的操作 undo log指事务开始之前,在操作任何数据之前,首先将需操作的数据备份到一个地方 (Undo Log)

UndoLog是为了实现事务的原子性而出现的产物

Undo Log实现事务原子性: 事务处理过程中如果出现了错误或者用户执行了 ROLLBACK语句,Mysql可以利用Undo Log中的备份将数据恢复到事物开始之前的状态

UndoLogMysql innodb存储引擎中用来实现多版本并发控制

Undo log实现多版本并发控制: 事务未提交之前,Undo保存了未提交之前的版本数据,Undo 中的数据可作为数据旧版本快照供其他并发事务进行快照读

mysql性能优化-MVCC_第8张图片

IBD文件存放在磁盘中,undo放在磁盘的表空间里面,MySQL把磁盘中的数据加载到缓冲区里面,我们要操作的数据全部在缓存区里面,操作完以后,MySQL可以通过一些策略将缓冲区里面的数据持久化到ibd文件里面去。undo buffer可以通过一定的策略定时的写到undo log里面去。
undo log的工作原理:把buffer区的数据先备份。
一旦事务提交了,undo在这里就没有意义了。

当前读,快照读

快照读:

SQL读取的数据是快照版本,也就是历史版本,普通的SELECT就是快照读 innodb快照读,数据的读取将由 cache(原本数据) + undo(事务修改过的数据) 两部分组成

当前读:

SQL读取的数据是最新版本。通过锁机制来保证读取的数据无法通过其他事务进行修改 UPDATEDELETEINSERTSELECT ... LOCK IN SHARE MODESELECT ... FOR UPDATE都是当前读

当前读
在整个InnoDB引擎里面,通过快照读的mvcc解决幻读问题,通过当前读的next-key(临键锁)解决幻读问题。
如果在写数据的时候,不让其他人去读,那么并发性能会收到影响。如果完全按照mvcc的方式的话,读取的数据有可能和预期的结果不一致。
update的时候上了X锁,就会把数据拷贝到undo logI里面, select的时候读快照,快照就是通过读Undo日志返回数据。
 

Redo log

Redo Log 是什么: Redo,顾名思义就是重做。以恢复操作为目的,重现操作; Redo log指事务中操作的任何数据,将最新的数据备份到一个地方 (Redo Log)

Redo log的持久: 不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo 中。具体的落盘策略可以进行配置

RedoLog是为了实现事务的持久性而出现的产物

Redo Log实现事务持久性: 防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。

 

mysql性能优化-MVCC_第9张图片

如果teacher.ibd有一个Update的操作加载到cache里面,update之后,没有提交,此时会立刻把这个数据更新到redo buffer里面,按照一定的策略写到redo log里面,(cache里面的数据相当于数据表在内存中的映射,每次提交的时候并不是把所有的数据都能刷到硬盘上,这样的话在commit的时候效率就会很低,因为要做很多次随机的io(redo buffer->log是顺序IO,log->ibd是随机IO,但是已经不影响效率了。)。每次cache里面的数据做了更新后,就会迅速更新到redo buffer里面,只要把redo buffer里面的数据写到了redo log里面,MySQL引擎就会认为此次事务提交成功了(持久化了),不会在乎脏页有没有刷到磁盘,脏页刷到磁盘的动作是在后台慢慢做的,(如果通过随机IO直接把数据包括脏页持久化到磁盘了,那么redo也就没有意义了,)但是数据并不一定已经刷到了磁盘里面。如果发生断电事故,只要redo buffer的数据写到了redo log里面,当再次重启的时候,MySQL会基于redo log日志进行数据的重做,会把提交过的数据全部恢复到teacher.ibd文件里面)。
 

Redo log补充知识点(参数配置)

指定Redolog记录在{datadir}/ib_logfile1&ib_logfile2 可通innodb_log_group_home_dir配置指定 目录存储

一旦事务成功提交且数据持久化落盘之后,此时Redo log中的对应事务数据记录就失去了意义,所 以Redo log的写入是日志文件循环写入的

指定Redo log日志文件组中的数量 innodb_log_files_in_group 默认为2

指定Redo log每一个日志文件最大存储量innodb_log_file_size 默认48M

指定Redo logcache/buffer中的buffer池大小innodb_log_buffer_size 默认16M

Redo buffer 持久化Redo log的策略Innodb_flush_log_at_trx_commit

 取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丢失一秒内 的事务数据]

取值 1 默认值,每次事务提交执行Redo buffer --> Redo log OS cache -->flush cache to disk [最安全,性能最差的方式]

取值 2 每次事务提交执行Redo buffer --> Redo log OS cache 再每一秒执行 ->flush cache to disk操作

建议取值2,MySQL挂了,损失一次事务数据,操作系统挂了,损失1秒事务数据。

你可能感兴趣的:(mysql-1.0,mysql1.0)