LightDB-事务并发控制之MVCC


LightDB22.3 MVCC

MVCC的实现方法

MVCC的实现方法有两种:

  1. 写新数据时,把旧数据移到一个单独的地方,如回滚段中,其他人读数据时,从回滚段中把旧的数据读出来;

  2. 写数据时,旧数据不删除,而是把新数据插入。

PostgreSQL MVCC

Oracle还有MySQL中不同的是,PostgreSQL中没有undo这一概念,PostgreSQL中的多版本并发是通过在表中数据行的多个版本来实现的,例如在一张表中我们要更新一条记录,PostgreSQL并不是直接修改该数据,而是通过插入一条全新的数据,同时对老数据加以标识。

PostgreSQL的MVCC实现方式的优缺点如下:

  • 优点:
  1. 事务回滚可以立即完成,无论事务进行了多少操作;

  2. 数据可以进行很多更新,不必像OracleMySQL的Innodb引擎那样需要经常保证回滚段不会被用完,也不会像Oracle数据库那样经常遇到“ORA-1555”错误的困扰;

  • 缺点:
  1. 旧版本数据需要清理。PostgreSQL清理旧版本的命令成为Vacuum

  2. 旧版本的数据会导致查询更慢一些,因为旧版本的数据存在于数据文件中,查询时需要扫描更多的数据块。

使用MVCC并发控制模型而不是锁定的主要优点是在MVCC中,对查询(读)数据的锁请求与写数据的锁请求不冲突,所以读不会阻塞写,而写也从不阻塞读。甚至在通过使用革新的可序列化快照隔离(SSI)级别提供最严格的事务隔离级别时,PostgreSQL也维持这个保证。

PostgreSQL里也有表和行级别的锁功能,用于那些通常不需要完整事务隔离并且想要显式管理特定冲突点的应用。不过,恰当地使用MVCC通常会提供比锁更好的性能。另外,由应用定义的咨询锁提供了一个获得不依赖于单一事务的锁的机制。

PostgreSQL的MVCC实现方式

通过HeapTupleFields:

typedef struct HeapTupleFields
{
	TransactionId t_xmin; /* inserting xact ID */
	TransactionId t_xmax; /* deleting or locking xact ID */
	
	union
	{
		CommandId t_cid; /* inserting or deleting command ID, or both */
		TransactionId t_xvac; /* old-style VACUUM FULL xact ID */
	}			t_field3
} HeapTupleFields;

PostgreSQL的MVCC实现是比较简单的。只需要通过对比tuple header中xmin,xmax,cmin,cmax与当前的xid,就可以得到在scan tuple时,此tuple对于当前查询的可视性。

几个关键的字段:

  • t_xmin:插入该元组的事务的txid;
  • t_xmax:删除或更新该元组的事务的txid,如果尚未删除或更新该元组,则t_xmax设置为0;
  • t_cid:命令ID(cid),这表示从0开始在当前事务中执行此命令之前已执行了多少个SQL命令;
  • t_ctid:指向自身或新元组的元组标识符(tid),当该元组被更新时,该元组的t_ctid指向新的元组,否则,t_ctid指向自身。

我们可以通过一个简单的例子来看看:

select xmin,xmax,ctid,* FROM accounts;

xmin  |xmax  |ctid  |id|user_name|balance  |
------+------+------+--+---------+---------+
101231|0     |(0,4) | 2|UserB    |   0.0000|
139206|139206|(0,14)| 1|UserA    |8000.0000|

2 row(s) fetched.

更新该表中的数据:

UPDATE accounts SET balance = 5000 WHERE id = 1;

可以看到id=1新记录的xmin被置为202860,ctid指向新的记录。

select xmin,xmax,ctid,* FROM accounts;

xmin  |xmax|ctid  |id|user_name|balance  |
------+----+------+--+---------+---------+
101231|0   |(0,4) | 2|UserB    |   0.0000|
202860|0   |(0,15)| 1|UserA    |5000.0000|

2 row(s) fetched.

总结

对比

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值