8.事务浅析

事务

事务的正确执行使得数据库从一种状态转换为另一种状态

事务的特性(ACID)

A atomicity : 要么成功要么失败--undo,mvcc
C consistency : 状态一致,数据完整性约束--对开发者的要求
I isolation : 事务间相互隔离,不能影响--lock,undo,mvcc
D durability : 事务正确提交,必须永久保留--redo,wal

并发事务下的问题

脏读:读未提交,数据不一样(update)
不可重复读*:同一个事务读取到不同数据
幻读:记录不一样(delete/insert)

事务隔离级别

隔离级别 脏读 不可重复读 幻读
read uncommit
read commit--pg默认
repeatable read
serialiable

----pg实现了三种,READ UNCOMMITTED和READ COMMITTED 一样

pg中的事务控制

  • begin :开启一个事务
  • commit : 提交
  • rollback :回滚
  • psql : 缺省autocommit-- \set AUTOCOMMIT off 关闭
  • 默认autocommit

MVCC

Multi-Version Concurrency Control:多版本并发控制
pg的实现方法:update/delete保留原有行,重新insert一条记录,旧的数据由vacuum做清理

事务号TXID

  • 每当事务开启时,事务管理器都会分配一个唯一的标识符,称为事务ID(TXID)
  • txid 32位无符号整数,最大2^32
  • 事务启动会执行内置txid_current(),返回当前txid
  • txid_current() 获取当前事务ID,当前无事务,分配一个
  • txid_current_if_assigned() 同上,当前无事务,返回null

事务的相关信息

存在于tuple head

  • xmin :插入该行版本的事务ID
  • xmax:删除此行的事务ID(delete/update),查询出来>0,说明未commit or rollback
  • cmin:insert,该事务中dml的序列,从0开始
  • cmax:update/delete,该事务中dml的序列,从0开始
  • ctid:行版本在其表中物理位置,类似于oracle rowid(),update和vacuum full会被改变

事务实现

每行有xmin和xmax两个字段

  • insert:xmin为当前事务ID,xmax为0
  • update:实际上insert一个新行,同上。同时,旧行的xmax置为当前事务ID
  • delete:将当前行的xmax设置为当前事务ID
    读到一行时,查询xmin和xmax对应的事务状态:committed、aborted、in progress,判断次行对当前行是否可见

事务ID的增长

  • 1.不会无限增长,最大2^32
  • 2.txid到最大值,又会从最小值3开始
    • 0:InvalidXID,无效事务ID
    • 1:BootstrapXID,表示系统表初始化时的事务ID,比任何普通的事务ID都旧
    • 2:FrozenXID,冻结的事务ID,比任何普通事务ID都旧
  • 3.同一个数据库中,存在的最旧和最新两个事务之间的年龄允许最大为2^31
  • pg的事务号最多只占2^32 序号中的一半
  • pg定期清理数据文件中过老的事务ID,使他们比所有普通事务ID都旧

事务可见性判定

  • 1.普通事务的比较方法
    ((int32)(id1 - id2)) < 0
    表达式为真,则id1比id2旧,为假则id1比id2新
最大事务ID为2^32 ,最小事务id为2^31 +1
2^32 - (2^31+2) = 2147483646
二进制
111 1111 1111 1111 1111 1111 1111 1110 > 0

最大事务ID为2^32,此时再来一个新事务,回卷之后为3
2^32 - 3 = 4294967293
二进制
1111   1111  1111  1111  1111  1111  1111 1101 < 0
  • 2.BootstrapXID比所有其他事务都旧,包括FrozenXID
  • 3.FrozenXID比普通事务旧
  • 4.数据中的每个sql都会有自己的事务号,这个事务号会记入SnapshotData,通过快照中的txid和tuple中的xmin和xmax对比,判断出当前行对当前事务是否可见.

事务快照相关函数

txid_current_snapshot() 获取当前快照
txid_snapshot_xip(txid_snapshot) 获取在快照中进行中的事务ID
txid_snapshot_xmax(txid_snapshot) 获取快照的 xmax
txid_snapshot_xmin(txid_snapshot) 获取快照的xmin
txid_visible_in_snapshot(bigint,txid_current_snapshot) 在快照中事务ID是否可见(不使用子事务ID)
txid_status(bigint) 获取当前事务的状态,committed、aborted、in progress 或者如果事务ID太老,则是null

获取当前快照

txid_current_snapshot()
格式xmin:xmax:xip_list

  • xmin:最早仍活跃的事务ID(以下简称XID),早于此XID的事务要么被提交并可见,要么回滚要么丢弃。
  • xmax:最后已完结事务(COMMITTED/ABORTED)的事务ID + 1。
  • xip_list:在”拍摄”快照时仍进行中的事务ID。该列表包含xmin和xmax之间的活动事务ID。

总结一下,简单来说,对于给定的XID:
XID ∈ [1,xmin),过去的事务,对此快照均可见;
XID ∈ [xmin,xmax),不考虑子事务的情况,仍处于IN_PROGRESS状态的,不可见;COMMITED状态,可见;ABORTED状态,不可见;
XID ∈ [xmax,∞),未来的事务,对此快照均不可见;

--session 1
testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current
--------------
         1303
testdb=# select txid_current_snapshot();
 txid_current_snapshot
-----------------------
 1303:1303:

--session 2
testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current
--------------
         1304

--session 3
testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current
--------------
         1305
         
--session 4
testdb=# begin;
BEGIN
testdb=# select txid_current();
 txid_current
--------------
         1306

--session 1
testdb=# select txid_current_snapshot();
 txid_current_snapshot
-----------------------
 1303:1303:
 
--session 4
testdb=# rollback;
ROLLBACK

--session 1
testdb=# select txid_current_snapshot();
 txid_current_snapshot
-----------------------
 1303:1307:1304,1305

--session 3
testdb=# rollback;
ROLLBACK

--session 1
testdb=# select txid_current_snapshot();
 txid_current_snapshot
-----------------------
 1303:1307:1304
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容