1.MVCC 简介
·MVCC(Multi-Version Concurrency Control)被称为多版本并发控制
·MVCC是来处理数据库中并发访问的问题,提高并发的访问效率。
·MVCC在维护数据的一致性和完整性的同时,尽量避免读写的阻塞。
传统数据库是通过lock 机制来保证数据的一致性和完整性,这样付出的代价是当锁请求无法响应时,待处理的请求必须进入等候队列,甚至等待超时不被处理。MVCC 避开了传统数据库的lock 机制,最大限度的减少了锁的竞争。
2.实现MVCC 的机制
·数据写入时,把旧版本数据移到其他地方,如回滚段中,读取数据时,在回滚段中把数据读出来。
·数据写入时,保留旧版本数据,并插入新数据。
postgresql 使用的是第二种,mysgl中InnoDB存储引擎使用的是第一种。
3.事务四大特性的实现
4.MVCC 涉及的概念
·xid,在PostgeSQL中,每个事务都存在一个唯一的id,也称为xid,可通过txid current()函数获取当前的事务id。
·tuple,每一行数据,称为一行元组,一个tuple。
·ctid,tuple中的隐藏字段,代表tuple的物理位置。
·xmin,tuple中的隐藏字段,在创建一个tuple时,记录此值为当前的事务id.
·xmax,tuple中的隐藏字段,默认为0,在删除tuple中,记录此值为当前的事务id。
·cmin/cmax,tuple中的隐藏字段,标识同一个事务中多个语句的顺序,从0开始。
其隐藏字段存放在pg_attribute 表中
插入一条数据后查看,当前的xmin 是750
再插入一条数据查看,当前的xmin 是751
修改第一条数据查看,第一条的xmin 变为了752
5.XACT:事务提交状态日志
IN PROGRESS 0正在进行中
COMMITTED 1已提交
ABORTED 2中止
SUB COMMITTED 3子事物
6.数据的修改过程
·首先 backend 开启是一个事务,获得一个事务号 XID;
·在这个事务中对数据的任意修改,都被 XID 标记。
·其他 backend 在扫描数据时,会看到被这个 XID 修改过的数据,根据当前的隔离级别,选择对这些数据是否可见(默认的读已提交隔离级别看不到这些数据)
·只有当此XID 最后被标记成commit (写 WAL commit log 和写 clog xact)后,其他的 backend 才能看到这个 XID 修改的数据。
7.MVCC的工作机制
PostgreSQL中的MVCC就是通过以上几个隐藏字段协同实现的下面举几个具体的例子来看下工作机制首先我们开启事务插入一条数据,其中ctid代表数据的物理位置,xmin为当前事务id,xmax为0继续在上个事务中再插入一条数据,因为在同一个事务中,可以看到cmin,cmax按顺序增长修改id为1的数据name为c此时id为1的ctid变为了(0,3),同时开启另外一个窗口,可以看到id为1的xmax标识为修改数据时的事务id,即代表此条tuple已删除。
8.MVCC 的优缺点.
优点:
·由于旧版本数据不在回滚段中,如果发生事务回滚,可以立即完成,无论事务大小。
·数据可以进行大批量更新,不用担心回滚段被耗光
缺点:
·旧版本的数据量太多会影响查询效率
·旧版本的数据需安清理
·事务id的存储是32bit,如果超出这个限制便会发生事务回卷,这样新事物就无法访问旧的记录了,为了解决mvcc带来的问题,PostgreSQL引入了vacuum功能,它可以回收利用因更新或删除操作而被标记为删除的磁盘空间,同时也能保证事务id不被用光而造成历史数据的丢。