上一章节提到了事务和锁,还有个概念有必要补充下,那就是数据库的mvcc(多版本并发控制)。我们先来看下这条查询sql。
select * from mytable where age>20 and age<50;
读者们在执行这条sql的时候有没有考虑过这样一个问题。如果在执行这条sql期间 恰巧又有其它的会话事务修改了符合上面查询条件的数据,那么在这种情况下,select语句 最终返回的结果是否会受到其它事务更新数据的影响呢?在实际线上生产环境中,是绝不会允许查询期间数据受其它事务更新影响这种情况发生的,否则相同的一个查询返回的结果可能就会出现多个版本了。oracle解决这个问题用到的主要技术就是mvcc。
mvcc确保了数据读一致性。它允许读取操作在不加锁的情况下获取一致的数据快照,同时还不会阻塞写入操作。在查询期间,不管有多少其它事务更新了符合查询条件的数据,不管事务是否成功提交,都不会影响到最终查询结果。
我们来细说说mvcc,mvcc主要由三个构件组成。
1,scn (System Change Number),每个事务或者查询语句开始时会获取当前 scn 作为"时间锚点",它是全局唯一的单调递增的时间钟。笔者常习惯理解成是个精确到极细的时间戳。
2,undo 表空间,里面有多个回滚段,存储的是undo日志数据。主要用于支持事务回滚、多版本并发控制和系统崩溃后的数据恢复(undo可以理解为不要"un"操作,还原成原来的,术语就是回滚操作。顺便提下还有个redo,redo可以理解为重做"re"操作。重复执行一次。术语就是前滚操作。这2个概念根据字面意思都是很容易理解的)。
3,数据行头信息和数据块(block)头部的交易槽ITL(感兴趣的事务列表),它们存储的主要信息分别如下:
rowdata_head_msg= {
lock_byte, -- 标记当前行是否被物理锁定
tx_slot, -- 指向ITL槽的索引号
scn, --记录该行最后一次修改的scn
}
block_head_itl= {
tx_id, -- 事务id
scn, --事务提交时的scn,未提交为空
undo_addr, --最新undo记录地址
flags --事务状态标志
}
数据每次更新之前会把更新前的数据以快照的形式存入到undo表空间,如果存入了多份快照就会以版本链的形式存在undo表空间里。mvcc通过undo表空间维护的数据版本链并结合scn的版本和数据块信息最终确认查询语句返回的数据版本。undo日志数据记录关键信息如下:
&nb

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



