高并发控制肯定是数据必须达到的一个标准, 在并发操作中,对于同一个数据,同时读和写的两个回话有可能产生不一致,所以出现了在高并发情况下如何保持性能又保持一致出现了MVCC,多版本并发

实现MVCC的方法有两种:

1)写数据时,将旧数据移到一个单独的地方,比如回滚段中,从回滚段把旧数据读回来

2)写数据时,旧数据不删除,而是插入新数据,旧数据写文件。

MySQL,Oracle基本上是通过第一种方式操作,而PostGres则通过第二种操作,

针对第一种来说第二种的劣势:旧版本的数据块需要清理,旧版本的数据因为在文件中,访问可能会造成I/O及扫描更多的数据块,

优势:数据可以进行很多更新,不必担心没有回滚段或者回滚段装不下数据,

         事物回滚可以立即完成,无论事物进行了多少操作,


针对多版本并发介绍几个要的术语

表中的隐含字段

oid tableoid ctid xmin xmax cmin cmax 后四个字段实现控制数据行是否对用户可见


事物ID回卷问题

Postgres的事物ID 0 代表无效 1 初始化 2 代表冻结 3才是正式开始的事物ID值,

pg的id值一直从3一直增加 达到4字节整数的最大值,然后再回头从3开始,pg比较新旧事物到底是前还是后,通过事物id值来看,如果现在达到最大值,那么比价9》3 他就认为9是最新的事物ID,其实这是有问题的,为了解决这个问题,pg规定两个事物id差的最大值不得超过2的31次幂,这样就不会产生回卷问题,比如(int32(id1-id2))<0 这个结果id1=9 id2=3 肯定成功,但是id1=3 id2= 9肯定就是负数不成功,


pg物理存储术语

Relation 表示表或者索引

Tuple表示行即MYSQL中的ROW 记录了版本控制的几个值,

Page 表示磁盘中的数据块

Buffer表示内存中的数据块

数据块默认8k最大32k,


数据块的空闲空间的管理

如果一个数据更新删除插入,肯定会缠上旧版本的数据,那么在数据块就会产生空闲的空间,那么这些空闲的空间如何回收利用,比如插入一个数据是如何选择空间的空间块的,

首先记录每个数据块空闲空间的大小,实现快速的查找合适的空闲空间块,每个表都会有oid,如果某个oid出现了空闲的空间块,那么就会产生表oid_fsm文件,这个文件就是记录了空闲块的信息


可见性映射表文件

Tuple更新之后,数据块不会马上清理掉,而是需要等待vacuum命令是清理,而_vm的文件就是记录了哪些需要清理,方便进程清理的时候只需要扫描这个表即可,另外一个就是该表记录的是行对全部事物是否可见,还是行对部分事物可见,

这里根据上面的可见性映射表文件引出一个Index-only-scans技术,就是因为此文件记录的是事物的可见性,所以根据此表判断从索引取回的数据是否对当前事物可见,就不需要再去访问表中的行了,个人理解这个就是不去扫描表了,直接扫描了这个_vm表,有待考究


另一个新技术HOT技术

更新后的新行与旧行在同一个数据块内,旧行会有一个指针,指向新行,这就不必更新索引了,这里涉及一个填充因子,好像是控制这个是不是要指向新的一个指针,