Mysql-MVCC

Mysql-MVCC

mysql默认隔离级别为Repeatable Read可重复读

  • 当前读

    读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。对于我们日常的操作,如:select ... in lock share mode(共享锁),

    select ... for update , select ... for update / insert / delete (排他锁)都是一种当前读

  • 快照读

    简单的select(不加锁,非阻塞读)就是快照读,读取的是记录的可见版本,有可能是历史数据(一个快照读伴随着一个ReadView)

    1. Read Committed : 每次select,都生成一个快照读

    2. Repeatable Read : 开启事务后,只有第一个select语言会生成快照读,之后的select都会复用快照

    3. Serializable : 快照读会退化为当前读

  • MVCC

    Multi-Version Concurrency Control 多版本并发控制

    维护一个数据的多个版本,使得读写操作没有冲突。快照读为MVCC提供了一个非阻塞读的功能。MVCC的具体实现,依赖于数据库记录的三个隐藏字段、undo log日志、ReadView。

    而给MVCC加上锁,就保证了事务的隔离性

    而一致性(事务执行前后,保证数据是一致的),而一致性事由redo log 和 undo log共同来保证的

  • 三个隐藏字段

    DB_TRX_ID : 事务ID,记录插入这条记录或最后一次修改记录的事务ID(自增)

    DR_ROLL_PTR : 回滚指针,指向这条记录的上一个版本,用于配合undo log

    DB_ROW_ID :隐藏主键,如果表结果没有指定主键,则会生成,否则不会

  • undo log 日志

    回滚日志,在insert、update、delete的时候产生,便于数据回滚

    当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后,可被立即删除

    而update,delete的时候,产生的undo log日志,需要在回滚和快照读中用到,不会被立即删除

  • undo log 版本链

    不同事务或相同事务对同一条记录进行修改,会导致该记录的undo log生成一条记录版本链表,链表的头部是最新的记录,链表的尾部是最开始的历史记录

  • ReadView 读视图

    快照读,读取的是当前可见记录(可能会有多个历史记录),那么到底读取那条记录,就是由ReadView来决定的,ReadView记录并维护系统当前活跃的事务ID(未提交)

    ReadView有四个核心字段:

    1. m_ids : 当前活跃的事务ID集合

    2. min_trx_id : 最小活跃事务ID

    3. max_trx_id : 预分配事务ID,当前最大事务ID+1

    4. creator_trx_id : ReadView创建者的事务ID

    实现原理:trx_id,当前undo log记录对应的当前事务ID,在决定获取那个历史版本数据时,就是拿trx_id和ReadView中的四个字段属性进行比对,取出匹配成功的记录

     

 

 

 

事务原理:

事务是一组操作集合,是一个不可分割的工作单位,事务会把所有操作作为一个整体一起提交或撤销,即:要么同时成功,要么同时失败

事务的四大特性:ACID

事务的原子性、一致性和持久性,是由innodb存储引擎底层的两份日志来保障的(undo log和redo log)

事务的隔离性,是由innodb存储引擎底层的锁机制和MVCC来实现的

redo log 重做日志

记录的是事务提交是数据页的物理修改,用来实现事务的持久性

该日志文件由两部分组成:重做日志缓冲(redo log buffer,存在内存中)和 重做日志文件(redo log file,存在磁盘中)。当事务提交之后,会把所有修改信息都存在该日志文件中,用于在刷新脏页数据到磁盘发生错误,用于数据的恢复使用。

undo log 回滚日志

主要用来解决事务的原子性

用于记录数据被修改前的信息,作用包含两个:回滚日志 和 MVCC(多版本并发控制)

undo log 记录的是逻辑日志,而 redo log记录的是物理日志。当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,他记录一条对应的反向update记录。当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。

undo log销毁:undo log在事务执行时产生,事务提交时,并不会立即删除,因为这些日志可能还用于MVCC

undo log存储:采用段的方式进行管理和记录,存放在rollback segment回滚段中,内部还有1024个undo log segment

全局锁:数据库备份时会加全局锁

元数据锁:对表结构的锁定。当有活跃的事务正在对表数据进行操作时,不允许对表结构进行修改

意向锁:解决行锁和表锁的冲突。当要加表锁时,会去扫描每行记录是否加有行锁,开销大,这个时候就有了意向锁(共享锁和排他锁),当加行锁时会自动加意向锁,当再加表锁时,表锁去查是否有意向锁就可以,则不需要遍历每行去处理了。

Mysql存储结构:

 

 

Buffer Pool:

 

 

Change Buffer:

mysql 5.x版本的时候是 插入缓冲区 insert buffer

mysql 8.0 开始,插入缓冲区 更换为 change buffer 更改缓冲区(针对二级索引)

 

 

Adaptive Hash Index 自适应hash:

 

 

Log Buffer 日志缓冲区:

 

 

System Tablespace && File-Per-Table Spaces

 

 

通用表空间 & Undo Tablespaces & 临时表空间

 

 

DoubleWrite Buffer File 双写缓冲区 & Redo Log 重做日志

 

 

后台线程的作用:在合适的时间将Buffer pool中的数据刷新到磁盘中

 

 

posted @ 2022-03-03 17:05  迷路小孩  阅读(54)  评论(0)    收藏  举报