• PostgreSQL事务实现


    事务简介

    • 事务管理器:有限状态机
      • 日志管理器
        • CLOG:事务的执行结果
        • XLOG:undo/redo日志
      • 锁管理器:实现并发控制,读阶段采用MVCC,写阶段采用锁控制实现不同的隔离级别

    PostgreSQL为每条事务创建一个postgre进程,并发执行事务。采用分层的机制执行事务,上层事务块和底层事务。上层事务块是用户眼中的事务,用于控制事务执行的状态;底层事务是事务中的每条语句,可以改变上层事务块的状态。

    上层事务块

    每个postgre进程只有一个事务块,上层事务块记录着本次事务执行过程中的各个状态。

    typedef enum TBlockState
    {
    	/* not-in-transaction-block states */
    	TBLOCK_DEFAULT,				/* idle */
    	TBLOCK_STARTED,				/* 执行简单查询事务 */
    
    	/* transaction block states */
    	TBLOCK_BEGIN,				/* 遇见事务开始BEGIN */
    	TBLOCK_INPROGRESS,			/* 事务正在执行中 */
    	TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
    	TBLOCK_END,					/* 遇见事务结束COMMIT/END的时候设置 */
    	TBLOCK_ABORT,				/* 事务出错,等待ROLLBACK */
    	TBLOCK_ABORT_END,			/* 事务出错,收到ROLLBACK */
    	TBLOCK_ABORT_PENDING,		/* 事务处理中,接收到ROLLBACK */
    	TBLOCK_PREPARE,				/* 事务处理中,收到PREPARE(分布式事务) */
    
    	/* subtransaction states */
    	TBLOCK_SUBBEGIN,			/* starting a subtransaction */
    	TBLOCK_SUBINPROGRESS,		/* live subtransaction */
    	TBLOCK_SUBRELEASE,			/* RELEASE received */
    	TBLOCK_SUBCOMMIT,			/* COMMIT received while TBLOCK_SUBINPROGRESS */
    	TBLOCK_SUBABORT,			/* failed subxact, awaiting ROLLBACK */
    	TBLOCK_SUBABORT_END,		/* failed subxact, ROLLBACK received */
    	TBLOCK_SUBABORT_PENDING,	/* live subxact, ROLLBACK received */
    	TBLOCK_SUBRESTART,			/* live subxact, ROLLBACK TO received */
    	TBLOCK_SUBABORT_RESTART		/* failed subxact, ROLLBACK TO received */
    } TBlockState;
    

    常见的事务块状态转换图
    image

    • startTransactionCommand:事务块中每条语句执行前都会调用。
    • commitTransactionCommand:事务块中每条语句执行结束都会调用
    • abortCurrentTransaction:事务块中语句执行错误,在调用点调用
    • BeginTransactionBlock:遇见BEGIN命令调用,状态变为TBLOCK_BEGIN
    • EndTransactionBlock:遇见END调用,可能成功提交,也可能回滚
    • AbortTransactionBlock:遇见ABORT指令调用

    底层事务

    底层事务是需要执行的每条命令,负责处理资源和锁的获取和释放,信号的处理,日志记录等等

    typedef enum TransState
    {
    	TRANS_DEFAULT,				/* idle */
    	TRANS_START,				/* transaction starting */
    	TRANS_INPROGRESS,			/* inside a valid transaction */
    	TRANS_COMMIT,				/* commit in progress */
    	TRANS_ABORT,				/* abort in progress */
    	TRANS_PREPARE				/* prepare in progress */
    } TransState;
    
    

    主要有四个函数:

    • StartTransaction:由BEGIN的startTransactionCommand调用,调用结束后事务块状态为TBLOCK_STARTED
    • CommitTransaction:由END的commitTransactionCommand调用,提交事务
    • AbortTransaction和CleanupTransaction:释放资源,恢复默认状态

    分布式事务

    PostgreSQL提供了分布式事务中的,两阶段提交的接口

    并发控制

    PostgreSQL采用MVCC的方式进行并发控制,每个事务看到的是一段时间前的数据快照。同时,MVCC并不能够解决所有问题,所以也提供了行级和表级的锁。

    标准的事务隔离级别有4个,而PostgreSQL只实现了读已提交和可串行化。

    PostgreSQL实现了8种锁(可怕)

    image

    太多了,就记住几个吧。

    • 行共享锁:select for update/for share
    • 表共享锁:select
    • 行排他锁:insert/update/delete
    • 表排他锁:drop

    加锁的对象

      • 表锁
      • 会话锁
      • 扩展锁:新增表空间
    • 页:对索引页面
    • 元组:
    • 事务:

    死锁处理

    image

    • postgresql检测出最后一个等待的杀掉,oracle是第一个等待的杀掉
    • 死锁检测算法(等待图)

    MVCC

    关键词:

    • 基于事务ID
    • 行级多版本
    • 无回滚段,行内存储
      • 一次UPDATE,产生记录两个版本
      • 两个版本都存在页面内部
    typedef struct HeapTupleFields
    {
    	TransactionId t_xmin;		/* Insert,Update事务 */
    	TransactionId t_xmax;		/* Delete,Update,Row Locks事务ID */
    
    	union
    	{
    		CommandId	t_cid;		/* 操作ID */
    		TransactionId t_xvac;	/* old-style VACUUM FULL xact ID */
    	}			t_field3;
    } HeapTupleFields;
    

    cmin:插入该元组的命令在插入事务中的命令标识(从0开始累加)
    cmax:删除该元组的命令在插入事务中的命令标识(从0开始累加)
    ctid:相当于rowid , <数据块ID,偏移量>
    XID:事务ID
    Xid_snapshot:当前系统中未提交的事务
    CLOG:事务状态日志(已提交的日志)

    隔离级别

    1. RC:读已提交
      1. 两个事务可以并发更新同一行
      2. 一个事务更新,一个事务删除同一行,删除操作会上锁
    2. RR:读未提交,其实是snapshot isolation,(冲突状态会回滚)
    3. 可串行化:serialize snapshot isolation,比标准可串行化要高,通过加内存中的意向锁实现,不允许预加锁的数据被其他事务变更

    数据可见性判断

    1. 记录的头部XID信息比当前事务更早(rr和ssi有这个要求,read commited没有这个要求,读已经提交可以读未来的事务!!)
    2. 记录头部的XID信息不在当前的XID_snapshot中,(记录上的事务状态不是未提交的事务)
    3. 记录头部的XID信息在CLOG中代表已提交。
    • MVCC需要判断该行数据在这个事务中的有效性,可见性,可更新性(需要锁的帮助才能正确执行隔离级别)
    • 判断条件:若xmin等于当前事务ID,则包含所有xmax=0(未被删除)的元组。
      若与xmin相等的事务ID对应的事务已经被提交,则包含所有xmax=0或xmax为当前事务ID的元组。
    • 实现概要
      • 对读不用加锁,对写加锁(只阻塞写),事务结束对比是否冲突

    多行数据需要过期版本回收

    1. 页面级:页面访问时回收
    2. 表级/系统级: autovacuum; vacuum

    日志

    1. pg_log:数据库活动日志(也就是数据库的操作日志);
    2. pg_xlog:事务日志,记录事务的执行过程,redo日志
    3. pg_clog:事务状态日志(pg_clog是pg_xlog的辅助日志),记录事务的结果。
  • 相关阅读:
    sencha touch 扩展篇之将sencha touch打包成安装程序(上)- 使用sencha cmd打包安装程序
    sencha touch 扩展篇之使用sass自定义主题样式 (下)通过css修改官方组件样式以及自定义图标
    一个不错的android组件的网站
    sencha touch 扩展篇之使用sass自定义主题样式 (上)使用官方的api修改主题样式
    sencha touch 入门系列 (九) sencha touch 布局layout
    面试题总结
    国外接活网站Elance, Freelancer和ScriptLance的介绍和对比
    sencha touch 入门系列 扩展篇之sencha touch 项目打包压缩
    Android Design Support Library——Navigation View
    设计模式——命令模式
  • 原文地址:https://www.cnblogs.com/biterror/p/7161631.html
Copyright © 2020-2023  润新知