怎么理解PostgreSQL事务管理
发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,本篇内容介绍了"怎么理解PostgreSQL事务管理"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一
千家信息网最后更新 2025年02月02日怎么理解PostgreSQL事务管理
本篇内容介绍了"怎么理解PostgreSQL事务管理"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
一、The Transaction System
README
src/backend/access/transam/READMEThe Transaction System======================事务系统PostgreSQL's transaction system is a three-layer system. The bottom layerimplements low-level transactions and subtransactions, on top of which reststhe mainloop's control code, which in turn implements user-visibletransactions and savepoints.PostgreSQL的事务分为3层,底层实现了低层次的事务和子事务,在其顶上驻留主循环控制代码,而主循环实现了用户可见性事务和保存点.The middle layer of code is called by postgres.c before and after theprocessing of each query, or after detecting an error: StartTransactionCommand CommitTransactionCommand AbortCurrentTransactionMeanwhile, the user can alter the system's state by issuing the SQL commandsBEGIN, COMMIT, ROLLBACK, SAVEPOINT, ROLLBACK TO or RELEASE. The traffic copredirects these calls to the toplevel routines BeginTransactionBlock EndTransactionBlock UserAbortTransactionBlock DefineSavepoint RollbackToSavepoint ReleaseSavepointrespectively. Depending on the current state of the system, these functionscall low level functions to activate the real transaction system: StartTransaction CommitTransaction AbortTransaction CleanupTransaction StartSubTransaction CommitSubTransaction AbortSubTransaction CleanupSubTransaction在处理查询的前后或者检测到错误时,postgres.c会调用中间层的代码: StartTransactionCommand CommitTransactionCommand AbortCurrentTransaction在此期间,通过执行BEGIN/COMMIT/ROLLBACK/SAVEPOINT/ROLLBACK TO/RELEASE命令改变系统状态.调度程序会把这些调用重定向至相应的顶层例程上. BeginTransactionBlock EndTransactionBlock UserAbortTransactionBlock DefineSavepoint RollbackToSavepoint ReleaseSavepoint依赖于当前的系统状态,这些函数调用底层函数激活真正的事务系统: StartTransaction CommitTransaction AbortTransaction CleanupTransaction StartSubTransaction CommitSubTransaction AbortSubTransaction CleanupSubTransactionAdditionally, within a transaction, CommandCounterIncrement is called toincrement the command counter, which allows future commands to "see" theeffects of previous commands within the same transaction. Note that this isdone automatically by CommitTransactionCommand after each query inside atransaction block, but some utility functions also do it internally to allowsome operations (usually in the system catalogs) to be seen by futureoperations in the same utility command. (For example, in DefineRelation it isdone after creating the heap so the pg_class row is visible, to be able tolock it.)另外,在事务内,调用CommandCounterIncrement增加命令计数,这可以让未来的命令可以看到在同一个事务中先前命令的影响.注意该动作由CommitTransactionCommand在事务块内部完成每个查询后自动完成,但某些工具函数同样会内部实现此功能以允许某些操作(通常在系统目录中)可被未来同样的工具命令看到.(比如,在DefineRelation,在创建堆后已完成,因此pg_class中的行已可见,并能执行锁定)For example, consider the following sequence of user commands:举个例子,考虑下面一组用户命令:1) BEGIN2) SELECT * FROM foo3) INSERT INTO foo VALUES (...)4) COMMITIn the main processing loop, this results in the following function callsequence:在主处理循环,会形成下面函数调用序列: / StartTransactionCommand; -- middle / StartTransaction; -- bottom1) < ProcessUtility; << BEGIN \ BeginTransactionBlock; -- top \ CommitTransactionCommand; -- middle / StartTransactionCommand; -- middle2) / PortalRunSelect; << SELECT ... \ CommitTransactionCommand; -- middle \ CommandCounterIncrement; / StartTransactionCommand; -- middle3) / ProcessQuery; << INSERT ... \ CommitTransactionCommand; -- middle \ CommandCounterIncrement; / StartTransactionCommand; -- middle / ProcessUtility; << COMMIT4) < EndTransactionBlock; -- top \ CommitTransactionCommand; -- middle \ CommitTransaction; -- bottomThe point of this example is to demonstrate the need forStartTransactionCommand and CommitTransactionCommand to be state smart -- theyshould call CommandCounterIncrement between the calls to BeginTransactionBlockand EndTransactionBlock and outside these calls they need to do normal start,commit or abort processing.该例子想表达的意思是StartTransactionCommand和CommitTransactionCommand需要具备状态智能-- 在BeginTransactionBlock/EndTransactionBlock之间需调用CommandCounterIncrement,在这些调用之外,它们需要执行常规的start,commit或abort处理.Furthermore, suppose the "SELECT * FROM foo" caused an abort condition. Inthis case AbortCurrentTransaction is called, and the transaction is put inaborted state. In this state, any user input is ignored except fortransaction-termination statements, or ROLLBACK TOcommands.而且,假定"SELECT * FROM foo"出错,导致需要abort,那么会调用AbortCurrentTransaction(bottom),事务状态为aborted状态.事务处于这个状态,除了事务终止语句或者ROLLBACK TO 命令外,所有用户输入都会被忽略.Transaction aborts can occur in two ways:事务取消的情况有两种:1) system dies from some internal cause (syntax error, etc) 内部原因,如语法错误等.2) user types ROLLBACK 用户类型的ROLLBACK.The reason we have to distinguish them is illustrated by the following twosituations:区分事务取消的原因如下两例所示: case 1 case 2 ------ ------1) user types BEGIN 1) user types BEGIN2) user does something 2) user does something3) user does not like what 3) system aborts for some reason she sees and types ABORT (syntax error, etc)In case 1, we want to abort the transaction and return to the default state.In case 2, there may be more commands coming our way which are part of thesame transaction block; we have to ignore these commands until we see a COMMITor ROLLBACK.第一种情况,用户希望取消事务并返回到默认状态.第二种情况,在同一个事务块中,可能会有更多的命令进入,需要忽略这些命令直至COMMIT/ROLLBACK.Internal aborts are handled by AbortCurrentTransaction, while user aborts arehandled by UserAbortTransactionBlock. Both of them rely on AbortTransactionto do all the real work. The only difference is what state we enter afterAbortTransaction does its work:* AbortCurrentTransaction leaves us in TBLOCK_ABORT,* UserAbortTransactionBlock leaves us in TBLOCK_ABORT_END内部的事务取消通过AbortCurrentTransaction(bottom)处理,而用户取消通过UserAbortTransactionBlock(top)处理.它们都需要依赖AbortTransaction(bottom)来处理实际的工作,不同的地方是在AbortTransaction后进入的状态不同:* AbortCurrentTransaction进入TBLOCK_ABORT* UserAbortTransactionBlock进入TBLOCK_ABORT_ENDLow-level transaction abort handling is divided in two phases:* AbortTransaction executes as soon as we realize the transaction has failed. It should release all shared resources (locks etc) so that we do not delay other backends unnecessarily.* CleanupTransaction executes when we finally see a user COMMIT or ROLLBACK command; it cleans things up and gets us out of the transaction completely. In particular, we mustn't destroy TopTransactionContext until this point.底层事务取消处理分为两个阶段:* 一旦感知事务已失败,则马上执行AbortTransaction,需要释放所有的共享资源(比如锁等)以便不影响其他后台进程.* 在用户发出COMMIT/ROLLBACK时执行CleanupTransaction;清理现场并完整的跳出事务. 特别地,在这个点上才需要销毁TopTransactionContextAlso, note that when a transaction is committed, we don't close it right away.Rather it's put in TBLOCK_END state, which means that whenCommitTransactionCommand is called after the query has finished processing,the transaction has to be closed. The distinction is subtle but important,because it means that control will leave the xact.c code with the transactionopen, and the main loop will be able to keep processing inside the sametransaction. So, in a sense, transaction commit is also handled in twophases, the first at EndTransactionBlock and the second atCommitTransactionCommand (which is where CommitTransaction is actuallycalled).同时,注意如果事务已提交,必须要马上关闭,而是进入TBLOCK_END状态,这意味着在查询完成后执行CommitTransactionCommand,事务才会关闭.这种区别很微妙,但很重要,因为控制已在事务开启的情况下从xact.c代码中跳出,主循环仍在相同的主事务中.因此,在某种意义上来说,事务提交存在两个阶段,首先EndTransactionBlock(top),其次CommitTransactionCommand(middle).(CommitTransactionCommand是实际调用CommitTransaction的地方)The rest of the code in xact.c are routines to support the creation andfinishing of transactions and subtransactions. For example, AtStart_Memorytakes care of initializing the memory subsystem at main transaction start.xact.c的剩余代码是用于支持创建和结束事务和子事务的例程.比如AtStart_Memory在主事务开启时处理初始化内存子系统.
TransactionState结构体
/* * transaction states - transaction state from server perspective */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;/* * transaction block states - transaction state of client queries * * Note: the subtransaction states are used only for non-topmost * transactions; the others appear only in the topmost transaction. */typedef enum TBlockState{ /* not-in-transaction-block states */ TBLOCK_DEFAULT, /* idle */ TBLOCK_STARTED, /* running single-query transaction */ /* transaction block states */ TBLOCK_BEGIN, /* starting transaction block */ TBLOCK_INPROGRESS, /* live transaction */ TBLOCK_IMPLICIT_INPROGRESS, /* live transaction after implicit BEGIN */ TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */ TBLOCK_END, /* COMMIT received */ TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */ TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */ TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */ TBLOCK_PREPARE, /* live xact, PREPARE received */ /* 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;/* * transaction state structure */typedef struct TransactionStateData{ FullTransactionId fullTransactionId; /* my FullTransactionId */ SubTransactionId subTransactionId; /* my subxact ID */ char *name; /* savepoint name, if any */ int savepointLevel; /* savepoint level */ TransState state; /* low-level state */ TBlockState blockState; /* high-level state */ int nestingLevel; /* transaction nesting depth */ int gucNestLevel; /* GUC context nesting depth */ MemoryContext curTransactionContext; /* my xact-lifetime context */ ResourceOwner curTransactionOwner; /* my query resources */ TransactionId *childXids; /* subcommitted child XIDs, in XID order */ int nChildXids; /* # of subcommitted child XIDs */ int maxChildXids; /* allocated size of childXids[] */ Oid prevUser; /* previous CurrentUserId setting */ int prevSecContext; /* previous SecurityRestrictionContext */ bool prevXactReadOnly; /* entry-time xact r/o state */ bool startedInRecovery; /* did we start in recovery? */ bool didLogXid; /* has xid been included in WAL record? */ int parallelModeLevel; /* Enter/ExitParallelMode counter */ bool chain; /* start a new block after this one */ struct TransactionStateData *parent; /* back link to parent */} TransactionStateData;typedef TransactionStateData *TransactionState;
"怎么理解PostgreSQL事务管理"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
事务
命令
状态
处理
用户
情况
系统
代码
函数
循环
实际
底层
更多
查询
事务管理
管理
不同
两个
例子
内容
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
门头沟区管理软件开发一体化
初一护苗网络安全课观后感
佛山市思赢互联网科技有限公司
工会网络安全工作计划
数据库能存储的最大数据
网络安全法宣传教育简报
郑州网络安全周地址
ssr无法与服务器建立安全
中国网络安全弱点
晴天信息网络安全
揭阳公安局网络安全监察大队
海澜之家数据库
网络安全处置平台
网络安全讲课的讲解
服务器托管 isp 费用
网络安全攻防技术实战论文
qq的服务器端口
服务器加油站好不好
云网络安全套件是什么意思
标本数据库管理
便宜服务器优惠
云车网络技术有限公司怎么样
安全检查服务器
很简单的网络安全手抄报
接入点内的服务器怎样设置
日月精灵宝可梦我的世界服务器
南京云问网络技术
中新软件类似软件开发
下一代网络技术的发展前景摘要
汽车行业软件开发流程图