oracle、mysql innoDB是这种
第一种:写新数据时,把原数据移到一个单独的位置,如回滚段中,其他用户读数据时,从回滚段中把原数据读出来。
pg是这种
第二种:写新数据时,原数据不删除,而是把新数据插入进来。
具体pg mvcc原理
xmin、xmax:
·新插入一行时,将新插入行的xmin填写为当前的事务ID,xmax填“0”。
·修改这一行时,实际上新插入一行,原数据行上的xmin不变, xmax改为当前的事务ID,新数据行上的xmin填为当前的事务ID,xmax 填“0”。
·删除一行时,把被删除行上的xmax填写当前的事务ID。
由上可知,xmin就是标记插入数据行的事 务ID,而xmax就是标记删除数据行的事务ID。
简单理解:
有xmax=事务id,这行就是要删的;xmin=事务id且xmax=0就是最新数据。
-------------------------------------------------------------------
删除数据只是xmax做上标记,并没有从数据块中真实删除、释放空间。
pg通过vaccum进程来回收之前的空间。默认pg中的autovacuum是打开的。当表更新到一定量,会自动开始回收空间。也可以关闭自动回收,改成业务低峰期手动vacuum。
一个事务执行失败,产生的数据并不会在回滚中清理掉,而是标记成无效。回滚数据会导致新的I/O,降低性能。只需要xmin、xmax对应的失误是成功提交还是回滚了,就可以知道数据是否有效。
clog日志
pg的事务状态记录在commit log中,简称clog,在pg_clog子目录下。
事务状态有4种
·TRANSACTION_STATUS_IN_PROGRESS=0x00:表示事务正在 进行中。
·TRANSACTION_STATUS_COMMITTED=0x01:表示事务已提 交。
·TRANSACTION_STATUS_ABORTED=0x02:表示事务已回滚。
·TRANSACTION_STATUS_SUB_COMMITTED=0x03:表示子事 务已提交。
事务ID,在PostgreSQL中有时缩写为xid,是一个32bit的数字。有以下3个特殊的事务ID是给系统内部使用的,代表特殊的含义。
·InvalidTransactionId=0:表示是无效的事务ID。
·BootstrapTransactionId=1:表示系统表初使化时的事务ID。
·FrozenTransactionId=2:冻结的事务ID。
所以数据库系统第一个正常的事务ID是从3开始的,然后连续递 增,达到最大值后,再从3开始。事务ID为0、1、2的始终保留。
事务id最大值是4字节最大整数,范围是3——最大值。
如果到达最大值,就会从3再开始,称为回卷。如果回卷前,比较事务id大小即可知道先后顺序,如果发生了回卷,小的id可能比大的id更时间靠后。解决回卷的问题,最早和最新的事务最多差231,超过就会把旧事务换成特殊的事务id,也就是FrozenTransactionId=2,冻结的事务id,再做比较,就会认为正常的事务id比冻结的id更新。
pg mvcc的优劣势
oracle、mysql innodb的mvcc都是旧数据记录在回滚段里,读取旧版本数据需要根据回滚段重构旧版本数据。
pg等于访问新的数据即可,等vaccum进程回收旧数据。
优势:
1、事务回滚可立即完成,
2、数据可很多次更新,不必像oracle、innodb那样保证回滚段不会用完,也不会有ORA-01555。
劣势:
1、旧数据需要清理(vacuum)
2、旧版本的数据会导致查询更慢,因为扫描的时候需要扫更多的数据库。