PostgreSQL技术内幕11:PostgreSQL事务原理解析-MVCC
liebian365 2024-11-05 11:46 20 浏览 0 评论
0.简介
本文主要介绍在事务模块中MVCC(多版本并发控制)常见的实现方式,优缺点以及PG事务模块中MVCC(多版本并发控制)的实现。
1.MVCC介绍
MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于数据库管理系统中的并发控制的方法。在传统的并发控制中,常用的简单方式是通过加锁来保证某一时刻数据只被一个事务修改,但这种方式可能会带来并发度的下降,尤其在高并发场景下,很可能导致性能瓶颈。MVCC主要通过维护数据的多个版本来解决传统锁机制的一些局限性,每个事务可以看到一个特定版本,从而使得读写操作可以互不干扰地执行,其核心在于,对于每个修改,不直接在原始数据上修改,而是创建一个新的数据版本来做修改,其他事务依然可以访问旧的数据,以此来提高并发度。当然MVCC也有其局限性,比如在高并发场景下可能因为多个版本导致占用较高内存。
2.MVCC常见的实现方式
MVCC常见的实现方式有两种:
1)修改旧数据前备份,在写新的数据时,把旧的数据备份到单独的一块空间,其他事务读取数据时,可以在备份空间中获取,比如MySQL innodb引擎的回滚段。
2)新数据不直接修改,而是采用插入的方式。
以上两种方式,功能上都能实现MVCC,都需要占用一定的空间,两者相比较,二的事务回滚更为方便,不会出现备份空间用尽的问题;一的话清理上会更为简单,不会导致数据扫描使得读数据增加。PG采用的是二,即采用插入方式实现的MVCC。
3.PG的MVCC实现
3.1 可见性判断
MVCC的实现,首先要有版本的概念,下面来看PG中的定义,然后以一个实际的例子来分析可见性的判断,定义如下:
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;
struct HeapTupleHeaderData
{
union
{
HeapTupleFields t_heap;
DatumTupleFields t_datum;
} t_choice;
ItemPointerData t_ctid; /* current TID of this or newer tuple (or a
* speculative insertion token) */
....
}
可以看到,在上面代码结构中,每个元组头部存储事务的t_xmin(数据插入的事务id),t_xmax(数据删除或更新的事务id)如果为0则表示还未被删除和更新,这两个值一旦被设计就不会再次变化。
下面通过一个例子来看一个更新操作的修改以及可见性的判断。
xmin | xmax | a | b |
10 | 0 | 2 | 2 |
Update t set a=6;
xmin | xmax | a | b |
10 | 11 | 2 | 2 |
11 | 0 | 6 | 2 |
上述描述了向当前表插入了一条数据的过程,初始a=2,b=2的记录是由事务id为10的事务插入,xmax为0即还没被删除或更新;然后执行update语句,将a的值设置为6,xmax的值更新为11(表示由id为11的事务删除),同时新增一条记录(不在原记录修改),此时虽然有两条数据,但其实应该只有一条,所以需要根据事务的快照和提交的记录来进行判断,也就是可见性的判断。
在PG中,是用snapshot来获取那些事务正在执行,通过snapshot来区分事务是正在执行还是已经完成了,如果事务尚未完成,那么事务的更新和写入对其他事务来说是不可见的。snapshot数据结构如下:
typedef struct SnapshotData
{
SnapshotSatisfiesFunc satisfies; /* tuple test function */
TransactionId xmin; /* all XID < xmin are visible to me */
TransactionId xmax; /* all XID >= xmax are invisible to me */
TransactionId *xip;
uint32 xcnt; /* # of xact ids in xip[] */
TransactionId *subxip;
int32 subxcnt; /* # of xact ids in subxip[] */
bool suboverflowed; /* has the subxip array overflowed? */
bool takenDuringRecovery; /* recovery-shaped snapshot? */
bool copied; /* false if it's a static snapshot */
CommandId curcid; /* in my xact, CID < curcid are visible */
uint32 speculativeToken;
uint32 active_count; /* refcount on ActiveSnapshot stack */
uint32 regd_count; /* refcount on RegisteredSnapshots */
pairingheap_node ph_node; /* link in the RegisteredSnapshots heap */
TimestampTz whenTaken; /* timestamp when snapshot was taken */
XLogRecPtr lsn; /* position in the WAL stream when taken */
} SnapshotData;
其中所有XID<xmin(已完成的)的事务都可见,所有XID>xmax的事务都不可见,而介于xmin和xmax之间的事务可能已完成也可能进行中,所以需要一个数组来存储(xip),如果在xmin和xmax之间的事务id在这个数组被发现,说明事务正在进行且尚未完成,不可见。
获取数据时,会先根据snapshot来判断事务是否已完成,如果未完成,则不可见,对于已完成的需要判断时提交还是取消,查询clog来进行判断。这里还有个性能优化,就是使用tuple中标志位来进行判断,减少clog查询。
3.2 提交/取消
在PG中,一个事务最终状态可能有两种:Commit/Abort。
1)Commit:提交时会写WAL和CLOG,提交后对于其他事务可见。
2)Abort: abort时会写WAL和CLOG,abort后对于其他事务不可见。
相关推荐
- 4万多吨豪华游轮遇险 竟是因为这个原因……
-
(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...
- “菜鸟黑客”必用兵器之“渗透测试篇二”
-
"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...
- 科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白
-
作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...
- 麦子陪你做作业(二):KEGG通路数据库的正确打开姿势
-
作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...
- 知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势
-
智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...
- 每日新闻播报(September 14)_每日新闻播报英文
-
AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...
- 香港新巴城巴开放实时到站数据 供科技界研发使用
-
中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...
- 5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper
-
本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...
- Qt动画效果展示_qt显示图片
-
今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...
- 如何从0到1设计实现一门自己的脚本语言
-
作者:dong...
- 三年级语文上册 仿写句子 需要的直接下载打印吧
-
描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...
- C++|那些一看就很简洁、优雅、经典的小代码段
-
目录0等概率随机洗牌:1大小写转换2字符串复制...
- 二年级上册语文必考句子仿写,家长打印,孩子照着练
-
二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)