本篇内容介绍了“怎么理解PostgreSQL事务管理”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、The Transaction System

README

src/backend/access/transam/READMETheTransactionSystem======================事务系统PostgreSQL'stransactionsystemisathree-layersystem.Thebottomlayerimplementslow-leveltransactionsandsubtransactions,ontopofwhichreststhemainloop'scontrolcode,whichinturnimplementsuser-visibletransactionsandsavepoints.PostgreSQL的事务分为3层,底层实现了低层次的事务和子事务,在其顶上驻留主循环控制代码,而主循环实现了用户可见性事务和保存点.Themiddlelayerofcodeiscalledbypostgres.cbeforeandaftertheprocessingofeachquery,orafterdetectinganerror:StartTransactionCommandCommitTransactionCommandAbortCurrentTransactionMeanwhile,theusercanalterthesystem'sstatebyissuingtheSQLcommandsBEGIN,COMMIT,ROLLBACK,SAVEPOINT,ROLLBACKTOorRELEASE.ThetrafficcopredirectsthesecallstothetoplevelroutinesBeginTransactionBlockEndTransactionBlockUserAbortTransactionBlockDefineSavepointRollbackToSavepointReleaseSavepointrespectively.Dependingonthecurrentstateofthesystem,thesefunctionscalllowlevelfunctionstoactivatetherealtransactionsystem:StartTransactionCommitTransactionAbortTransactionCleanupTransactionStartSubTransactionCommitSubTransactionAbortSubTransactionCleanupSubTransaction在处理查询的前后或者检测到错误时,postgres.c会调用中间层的代码:StartTransactionCommandCommitTransactionCommandAbortCurrentTransaction在此期间,通过执行BEGIN/COMMIT/ROLLBACK/SAVEPOINT/ROLLBACKTO/RELEASE命令改变系统状态.调度程序会把这些调用重定向至相应的顶层例程上.BeginTransactionBlockEndTransactionBlockUserAbortTransactionBlockDefineSavepointRollbackToSavepointReleaseSavepoint依赖于当前的系统状态,这些函数调用底层函数激活真正的事务系统:StartTransactionCommitTransactionAbortTransactionCleanupTransactionStartSubTransactionCommitSubTransactionAbortSubTransactionCleanupSubTransactionAdditionally,withinatransaction,CommandCounterIncrementiscalledtoincrementthecommandcounter,whichallowsfuturecommandsto"see"theeffectsofpreviouscommandswithinthesametransaction.NotethatthisisdoneautomaticallybyCommitTransactionCommandaftereachqueryinsideatransactionblock,butsomeutilityfunctionsalsodoitinternallytoallowsomeoperations(usuallyinthesystemcatalogs)tobeseenbyfutureoperationsinthesameutilitycommand.(Forexample,inDefineRelationitisdoneaftercreatingtheheapsothepg_classrowisvisible,tobeabletolockit.)另外,在事务内,调用CommandCounterIncrement增加命令计数,这可以让未来的命令可以看到在同一个事务中先前命令的影响.注意该动作由CommitTransactionCommand在事务块内部完成每个查询后自动完成,但某些工具函数同样会内部实现此功能以允许某些操作(通常在系统目录中)可被未来同样的工具命令看到.(比如,在DefineRelation,在创建堆后已完成,因此pg_class中的行已可见,并能执行锁定)Forexample,considerthefollowingsequenceofusercommands:举个例子,考虑下面一组用户命令:1)BEGIN2)SELECT*FROMfoo3)INSERTINTOfooVALUES(...)4)COMMITInthemainprocessingloop,thisresultsinthefollowingfunctioncallsequence:在主处理循环,会形成下面函数调用序列:/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;--bottomThepointofthisexampleistodemonstratetheneedforStartTransactionCommandandCommitTransactionCommandtobestatesmart--theyshouldcallCommandCounterIncrementbetweenthecallstoBeginTransactionBlockandEndTransactionBlockandoutsidethesecallstheyneedtodonormalstart,commitorabortprocessing.该例子想表达的意思是StartTransactionCommand和CommitTransactionCommand需要具备状态智能--在BeginTransactionBlock/EndTransactionBlock之间需调用CommandCounterIncrement,在这些调用之外,它们需要执行常规的start,commit或abort处理.Furthermore,supposethe"SELECT*FROMfoo"causedanabortcondition.InthiscaseAbortCurrentTransactioniscalled,andthetransactionisputinabortedstate.Inthisstate,anyuserinputisignoredexceptfortransaction-terminationstatements,orROLLBACKTO<savepoint>commands.而且,假定"SELECT*FROMfoo"出错,导致需要abort,那么会调用AbortCurrentTransaction(bottom),事务状态为aborted状态.事务处于这个状态,除了事务终止语句或者ROLLBACKTO<savepoint>命令外,所有用户输入都会被忽略.Transactionabortscanoccurintwoways:事务取消的情况有两种:1)systemdiesfromsomeinternalcause(syntaxerror,etc)内部原因,如语法错误等.2)usertypesROLLBACK用户类型的ROLLBACK.Thereasonwehavetodistinguishthemisillustratedbythefollowingtwosituations:区分事务取消的原因如下两例所示:case1case2------------1)usertypesBEGIN1)usertypesBEGIN2)userdoessomething2)userdoessomething3)userdoesnotlikewhat3)systemabortsforsomereasonsheseesandtypesABORT(syntaxerror,etc)Incase1,wewanttoabortthetransactionandreturntothedefaultstate.Incase2,theremaybemorecommandscomingourwaywhicharepartofthesametransactionblock;wehavetoignorethesecommandsuntilweseeaCOMMITorROLLBACK.第一种情况,用户希望取消事务并返回到默认状态.第二种情况,在同一个事务块中,可能会有更多的命令进入,需要忽略这些命令直至COMMIT/ROLLBACK.InternalabortsarehandledbyAbortCurrentTransaction,whileuserabortsarehandledbyUserAbortTransactionBlock.BothofthemrelyonAbortTransactiontodoalltherealwork.TheonlydifferenceiswhatstateweenterafterAbortTransactiondoesitswork:*AbortCurrentTransactionleavesusinTBLOCK_ABORT,*UserAbortTransactionBlockleavesusinTBLOCK_ABORT_END内部的事务取消通过AbortCurrentTransaction(bottom)处理,而用户取消通过UserAbortTransactionBlock(top)处理.它们都需要依赖AbortTransaction(bottom)来处理实际的工作,不同的地方是在AbortTransaction后进入的状态不同:*AbortCurrentTransaction进入TBLOCK_ABORT*UserAbortTransactionBlock进入TBLOCK_ABORT_ENDLow-leveltransactionaborthandlingisdividedintwophases:*AbortTransactionexecutesassoonaswerealizethetransactionhasfailed.Itshouldreleaseallsharedresources(locksetc)sothatwedonotdelayotherbackendsunnecessarily.*CleanupTransactionexecuteswhenwefinallyseeauserCOMMITorROLLBACKcommand;itcleansthingsupandgetsusoutofthetransactioncompletely.Inparticular,wemustn'tdestroyTopTransactionContextuntilthispoint.底层事务取消处理分为两个阶段:*一旦感知事务已失败,则马上执行AbortTransaction,需要释放所有的共享资源(比如锁等)以便不影响其他后台进程.*在用户发出COMMIT/ROLLBACK时执行CleanupTransaction;清理现场并完整的跳出事务.特别地,在这个点上才需要销毁TopTransactionContextAlso,notethatwhenatransactioniscommitted,wedon'tcloseitrightaway.Ratherit'sputinTBLOCK_ENDstate,whichmeansthatwhenCommitTransactionCommandiscalledafterthequeryhasfinishedprocessing,thetransactionhastobeclosed.Thedistinctionissubtlebutimportant,becauseitmeansthatcontrolwillleavethexact.ccodewiththetransactionopen,andthemainloopwillbeabletokeepprocessinginsidethesametransaction.So,inasense,transactioncommitisalsohandledintwophases,thefirstatEndTransactionBlockandthesecondatCommitTransactionCommand(whichiswhereCommitTransactionisactuallycalled).同时,注意如果事务已提交,必须要马上关闭,而是进入TBLOCK_END状态,这意味着在查询完成后执行CommitTransactionCommand,事务才会关闭.这种区别很微妙,但很重要,因为控制已在事务开启的情况下从xact.c代码中跳出,主循环仍在相同的主事务中.因此,在某种意义上来说,事务提交存在两个阶段,首先EndTransactionBlock(top),其次CommitTransactionCommand(middle).(CommitTransactionCommand是实际调用CommitTransaction的地方)Therestofthecodeinxact.careroutinestosupportthecreationandfinishingoftransactionsandsubtransactions.Forexample,AtStart_Memorytakescareofinitializingthememorysubsystematmaintransactionstart.xact.c的剩余代码是用于支持创建和结束事务和子事务的例程.比如AtStart_Memory在主事务开启时处理初始化内存子系统.

TransactionState结构体

/**transactionstates-transactionstatefromserverperspective*/typedefenumTransState{TRANS_DEFAULT,/*idle*/TRANS_START,/*transactionstarting*/TRANS_INPROGRESS,/*insideavalidtransaction*/TRANS_COMMIT,/*commitinprogress*/TRANS_ABORT,/*abortinprogress*/TRANS_PREPARE/*prepareinprogress*/}TransState;/**transactionblockstates-transactionstateofclientqueries**Note:thesubtransactionstatesareusedonlyfornon-topmost*transactions;theothersappearonlyinthetopmosttransaction.*/typedefenumTBlockState{/*not-in-transaction-blockstates*/TBLOCK_DEFAULT,/*idle*/TBLOCK_STARTED,/*runningsingle-querytransaction*//*transactionblockstates*/TBLOCK_BEGIN,/*startingtransactionblock*/TBLOCK_INPROGRESS,/*livetransaction*/TBLOCK_IMPLICIT_INPROGRESS,/*livetransactionafterimplicitBEGIN*/TBLOCK_PARALLEL_INPROGRESS,/*livetransactioninsideparallelworker*/TBLOCK_END,/*COMMITreceived*/TBLOCK_ABORT,/*failedxact,awaitingROLLBACK*/TBLOCK_ABORT_END,/*failedxact,ROLLBACKreceived*/TBLOCK_ABORT_PENDING,/*livexact,ROLLBACKreceived*/TBLOCK_PREPARE,/*livexact,PREPAREreceived*//*subtransactionstates*/TBLOCK_SUBBEGIN,/*startingasubtransaction*/TBLOCK_SUBINPROGRESS,/*livesubtransaction*/TBLOCK_SUBRELEASE,/*RELEASEreceived*/TBLOCK_SUBCOMMIT,/*COMMITreceivedwhileTBLOCK_SUBINPROGRESS*/TBLOCK_SUBABORT,/*failedsubxact,awaitingROLLBACK*/TBLOCK_SUBABORT_END,/*failedsubxact,ROLLBACKreceived*/TBLOCK_SUBABORT_PENDING,/*livesubxact,ROLLBACKreceived*/TBLOCK_SUBRESTART,/*livesubxact,ROLLBACKTOreceived*/TBLOCK_SUBABORT_RESTART/*failedsubxact,ROLLBACKTOreceived*/}TBlockState;/**transactionstatestructure*/typedefstructTransactionStateData{FullTransactionIdfullTransactionId;/*myFullTransactionId*/SubTransactionIdsubTransactionId;/*mysubxactID*/char*name;/*savepointname,ifany*/intsavepointLevel;/*savepointlevel*/TransStatestate;/*low-levelstate*/TBlockStateblockState;/*high-levelstate*/intnestingLevel;/*transactionnestingdepth*/intgucNestLevel;/*GUCcontextnestingdepth*/MemoryContextcurTransactionContext;/*myxact-lifetimecontext*/ResourceOwnercurTransactionOwner;/*myqueryresources*/TransactionId*childXids;/*subcommittedchildXIDs,inXIDorder*/intnChildXids;/*#ofsubcommittedchildXIDs*/intmaxChildXids;/*allocatedsizeofchildXids[]*/OidprevUser;/*previousCurrentUserIdsetting*/intprevSecContext;/*previousSecurityRestrictionContext*/boolprevXactReadOnly;/*entry-timexactr/ostate*/boolstartedInRecovery;/*didwestartinrecovery?*/booldidLogXid;/*hasxidbeenincludedinWALrecord?*/intparallelModeLevel;/*Enter/ExitParallelModecounter*/boolchain;/*startanewblockafterthisone*/structTransactionStateData*parent;/*backlinktoparent*/}TransactionStateData;typedefTransactionStateData*TransactionState;

“怎么理解PostgreSQL事务管理”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!