6、MVCC多版本并发控制
2021-12-01 14:52:28 59 举报
MVCC(多版本并发控制)是一种数据库管理系统中的并发控制技术,它允许多个事务同时访问同一数据项,而每个事务都能看到其他事务对该数据项所做的修改。这种技术通过为每个数据项创建多个版本来实现,每个版本都有一个时间戳,用于记录该版本何时被创建。当一个事务需要读取或修改一个数据项时,它会获得该数据项的一个快照,该快照包含了所有大于等于该事务开始时间的版本。这样,即使其他事务在当前事务运行期间修改了该数据项,当前事务也只会看到它自己的快照中的数据项状态,从而避免了读写冲突和脏读等问题。
作者其他创作
大纲/内容
两阶段提交
I
updatecommit
记录最近更新这条行记录的事务 ID
读未提交
DB_TRX_ID
1
sex
持久性
优化器
实现原理
写入redolog处于prepare阶段
name
18
SC
trx_list
0
RU
20
InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。举个列子:当我们修改的时候,写完内存了(buffer),但数据还没真正写到磁盘的时候。此时我们的数据库挂了,我们可以对数据进行恢复。
begin
age
第二次select,RR隔离级别会复用上一次的ReadView
时刻
undolog
答案:都能
写入新行
提交事务处于commit状态
活跃事务列表中最小的事务ID
binlog
执行器
readview
4
男
回滚rollback
null
张三
一致性
当前系统活跃的事务列表
当前系统尚未分配的下一个事务ID
要么全部成功要么全部失败
2
DB_ROW_ID
3
连接器
MVCC(Multi-Version Concurrency Control):多版本并发控制,是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
分析器
此时执行select的时候,RC和RR隔离级别下,是否可以读取到最新修改的数据?
记录了sql操作的反向记录
返回行数据
隔离性
update xxx set c=c=1 where id =2
AID都是为了保证C
这里的两阶段提交可不是事务的,而是mysql日志的
t2
redolog
0x123
low_limit_id
ACID
新行更新到内存
1、先写 redo log 后写 binlog假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。由于我们前面说过的,redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。然后你会发现,如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。2、 先写 binlog 后写 redo log如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。
快照读
RR
表示指向该行回滚段(rollback segment)的指针,大小为7个字节,InnoDB便是通过这个指针找到之前版本的数据。该行记录上所有旧版本,在undo中都通过链表的形式组织。
select
DB_ROLL_PTR
事务1执行一条插入语句insert into user(“张三”,18,“男”)
事务
常用的两种,mysql默认是RR隔离级别越高,性能越差隔离级别越低,性能越高
MVCC锁
第二阶段
将这行的C值加1
SQL查询
写入binlog
undolog:回滚日志,保存了事务发生之前的数据的一个版本,作用:1、可以用于回滚2、同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。3、事务开始之前,将当前事务版本生成 undo log,undo log 也会产生 redo log 来保证 undo log 的可靠性。4、当事务提交之后,undo log 并不能立马被删除,而是放入待清理的链表。5、由 purge 线程判断是否有其它事务在使用 undo 段中表的上一个事务之前的版本信息,从而决定是否可以清理 undo log 的日志空间。
up_limit_id
undolog日志
select lock in share modeselect for updateinsert/delete/update
WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。
mysql三个重要的日志
逻辑日志
... ...
当事务在进行快照读的时候,会生成一个读视图来进行可见性判断,可见性判断是由可见性算法来确定的。读视图有三个关键的变量如下
记录最近更新这条行记录的事务 ID,大小为6个字节
t1
1,2
读已提交
Crash-Safe概念
A
分析
指向
原子性
否
提交commit
WAL
数据页在内存中?
如何理解MVCC?
本篇重点!!!
总结:能否看到事务修改的数据,取决于可见性算法,可见性算法比较的时候又取决于ReadView中的结果值!因为在不同隔离级别的时候,生成ReadView的时机是不同的RC:每次执行时快照读都会重新生成新的ReadViewRR:只有当第一次事务进行快照读的时候才会生成ReadView,之后的快照读操作都会复用当前的ReadView
C
隐藏字段
答案:RC可以,RR不可以
注意,这两个唯一不同的是,RC和RR生成Read View的时机不一样,所以导致可见性算法在做条件判断的时候也不一样!
当前读
属于存储引擎InnoDB特有的日志;redo log 记载着每次在某个页上做了什么修改。写redo log也是需要写磁盘的,但它的好处就是顺序IO(我们都知道顺序IO比随机IO快非常多)。写入的速度很快
RC
事务2修改age=20update user set age=20 where name='张三'
李四
可见性算法的判断步骤1、首先比较DB_TRX_ID < up_limit_id,如果小于,则当前事务能看到DB_TRX_ID所在的记录,如果大于或等于则进入下一个判断。2、接下来判断Db_TRX_ID >=low_limit_id,如果条件符合,则代表DB_TRX_ID所在的记录在ReadView生成后才出现的,那么对于当前事务来说,肯定看不见DB_TRX_ID所在的记录,则再进入下一个判断。3、判断DB_TRX_ID是否在trx_list活跃事务列表中,如果在,则代表在ReadView生成时,这个事务还是活跃状态,还没有commit,修改的数据,对当前事务是不可见的,如果不在,则说明这个事务在ReadView生成之前就已经开始commit了,那么修改的结果对当前事务来说是可以看见的
行标识(隐藏单调自增ID),大小为6字节,如果表没有主键,InnoDB会自动生成一个隐藏主键,因此会出现这个列。另外,每条记录的头信息(record header)里都有一个专门的bit(deleted_flag)来表示当前记录是否已经被删除。
磁盘中读入内存
一定要清楚这两个概念!
如果实际数据没有写入成功(可能由于突然断电,服务器突然crash掉),但只要记录到了日志中,当服务器重新启动后就可以根据日志中的记录恢复数据
第一次select,生成ReadView
串行化
可重复读
事务3修改name=‘李四’update user set name=‘李四’ where name='张三'
D
0x456
第一阶段
取ID=2这一行
物理日志
存储引擎
读读:不会存在任何问题,也不需要并发控制读写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读,需要MVCC控制写写:有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失
当前系统活跃的事务ID列表
二进制日志,全称binary log,存储着每条变更的SQL语句,也称归档日志,其属于MySQL Server,MySQL实例,真正提供数据存储和数据处理功能的MySQL服务器进程。
0 条评论
回复 删除
下一页