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

一、数据结构

BufferDesc
共享缓冲区的共享描述符(状态)数据

/**Flagsforbufferdescriptors*buffer描述器标记**Note:TAG_VALIDessentiallymeansthatthereisabufferhashtable*entryassociatedwiththebuffer'stag.*注意:TAG_VALID本质上意味着有一个与缓冲区的标记相关联的缓冲区散列表条目。*///bufferheader锁定#defineBM_LOCKED(1U<<22)/*bufferheaderislocked*///数据需要写入(标记为DIRTY)#defineBM_DIRTY(1U<<23)/*dataneedswriting*///数据是有效的#defineBM_VALID(1U<<24)/*dataisvalid*///已分配buffertag#defineBM_TAG_VALID(1U<<25)/*tagisassigned*///正在R/W#defineBM_IO_IN_PROGRESS(1U<<26)/*readorwriteinprogress*///上一个I/O出现错误#defineBM_IO_ERROR(1U<<27)/*previousI/Ofailed*///开始写则变DIRTY#defineBM_JUST_DIRTIED(1U<<28)/*dirtiedsincewritestarted*///存在等待solepin的其他进程#defineBM_PIN_COUNT_WAITER(1U<<29)/*havewaiterforsolepin*///checkpoint发生,必须刷到磁盘上#defineBM_CHECKPOINT_NEEDED(1U<<30)/*mustwriteforcheckpoint*///持久化buffer(不是unlogged或者初始化fork)#defineBM_PERMANENT(1U<<31)/*permanentbuffer(notunlogged,*orinitfork)*//**BufferDesc--shareddescriptor/statedataforasinglesharedbuffer.*BufferDesc--共享缓冲区的共享描述符(状态)数据**Note:Bufferheaderlock(BM_LOCKEDflag)mustbeheldtoexamineorchange*thetag,stateorwait_backend_pidfields.Ingeneral,bufferheaderlock*isaspinlockwhichiscombinedwithflags,refcountandusagecountinto*singleatomicvariable.Thislayoutallowustodosomeoperationsina*singleatomicoperation,withoutactuallyacquiringandreleasingspinlock;*forinstance,increaseordecreaserefcount.buf_idfieldneverchanges*afterinitialization,sodoesnotneedlocking.freeNextisprotectedby*thebuffer_strategy_locknotbufferheaderlock.TheLWLockcantakecare*ofitself.Thebufferheaderlockis*not*usedtocontrolaccesstothe*datainthebuffer!*注意:必须持有Bufferheader锁(BM_LOCKED标记)才能检查或修改tag/state/wait_backend_pid字段.*通常来说,bufferheaderlock是spinlock,它与标记位/参考计数/使用计数组合到单个原子变量中.*这个布局设计允许我们执行原子操作,而不需要实际获得或者释放spinlock(比如,增加或者减少参考计数).*buf_id字段在初始化后不会出现变化,因此不需要锁定.*freeNext通过buffer_strategy_lock锁而不是bufferheaderlock保护.*LWLock可以很好的处理自己的状态.*务请注意的是:bufferheaderlock不用于控制buffer中的数据访问!**It'sassumedthatnobodychangesthestatefieldwhilebufferheaderlock*isheld.Thusbufferheaderlockholdercandocomplexupdatesofthe*statevariableinsinglewrite,simultaneouslywithlockrelease(cleaning*BM_LOCKEDflag).Ontheotherhand,updatingofstatewithoutholding*bufferheaderlockisrestrictedtoCAS,whichinsurethatBM_LOCKEDflag*isnotset.Atomicincrement/decrement,OR/ANDetc.arenotallowed.*假定在持有bufferheaderlock的情况下,没有人改变状态字段.*持有bufferheaderlock的进程可以执行在单个写操作中执行复杂的状态变量更新,*同步的释放锁(清除BM_LOCKED标记).*换句话说,如果没有持有bufferheaderlock的状态更新,会受限于CAS,*这种情况下确保BM_LOCKED没有被设置.*比如原子的增加/减少(AND/OR)等操作是不允许的.**Anexceptionisthatifwehavethebufferpinned,itstagcan'tchange*underneathus,sowecanexaminethetagwithoutlockingthebufferheader.*Also,inplaceswedoone-timereadsoftheflagswithoutbotheringto*lockthebufferheader;thisisgenerallyforsituationswherewedon't*expecttheflagbitbeingtestedtobechanging.*一种例外情况是如果我们已有bufferpinned,该buffer的tag不能改变(在本进程之下),*因此不需要锁定bufferheader就可以检查tag了.*同时,在执行一次性的flags读取时不需要锁定bufferheader.*这种情况通常用于我们不希望正在测试的flagbit将被改变.**Wecan'tphysicallyremoveitemsfromadiskpageifanotherbackendhas*thebufferpinned.Hence,abackendmayneedtowaitforallotherpins*togoaway.ThisissignaledbystoringitsownPIDinto*wait_backend_pidandsettingflagbitBM_PIN_COUNT_WAITER.Atpresent,*therecanbeonlyonesuchwaiterperbuffer.*如果其他进程有bufferpinned,那么进程不能物理的从磁盘页面中删除items.*因此,后台进程需要等待其他pins清除.这可以通过存储它自己的PID到wait_backend_pid中,*并设置标记位BM_PIN_COUNT_WAITER.*目前,每个缓冲区只能由一个等待进程.**Weusethissamestructforlocalbufferheaders,butthelocksarenot*usedandnotalloftheflagbitsareusefuleither.Toavoidunnecessary*overhead,manipulationsofthestatefieldshouldbedonewithoutactual*atomicoperations(i.e.onlypg_atomic_read_u32()and*pg_atomic_unlocked_write_u32()).*本地缓冲头部使用同样的结构,但并不需要使用locks,而且并不是所有的标记位都使用.*为了避免不必要的负载,状态域的维护不需要实际的原子操作*(比如只有pg_atomic_read_u32()andpg_atomic_unlocked_write_u32())**Becarefultoavoidincreasingthesizeofthestructwhenaddingor*reorderingmembers.Keepingitbelow64bytes(themostcommonCPU*cachelinesize)isfairlyimportantforperformance.*在增加或者记录成员变量时,小心避免增加结构体的大小.*保持结构体大小在64字节内(通常的CPU缓存线大小)对于性能是非常重要的.*/typedefstructBufferDesc{//buffertagBufferTagtag;/*IDofpagecontainedinbuffer*///buffer索引编号(0开始),指向相应的bufferpoolslotintbuf_id;/*buffer'sindexnumber(from0)*//*stateofthetag,containingflags,refcountandusagecount*///tag状态,包括flags/refcount和usagecountpg_atomic_uint32state;//pin-count等待进程IDintwait_backend_pid;/*backendPIDofpin-countwaiter*///空闲链表链中下一个空闲的bufferintfreeNext;/*linkinfreelistchain*///缓冲区内容锁LWLockcontent_lock;/*tolockaccesstobuffercontents*/}BufferDesc;

BufferTag
Buffer tag标记了buffer存储的是磁盘中哪个block

/**Buffertagidentifieswhichdiskblockthebuffercontains.*Buffertag标记了buffer存储的是磁盘中哪个block**Note:theBufferTagdatamustbesufficienttodeterminewheretowritethe*block,withoutreferencetopg_classorpg_tablespaceentries.It's*possiblethatthebackendflushingthebufferdoesn'tevenbelievethe*relationisvisibleyet(itsxactmayhavestartedbeforethexactthat*createdtherel).Thestoragemanagermustbeabletocopeanyway.*注意:BufferTag必须足以确定如何写block而不需要参照pg_class或者pg_tablespace数据字典信息.*有可能后台进程在刷新缓冲区的时候深圳不相信关系是可见的(事务可能在创建rel的事务之前).*存储管理器必须可以处理这些事情.**Note:ifthere'sanypadbytesinthestruct,INIT_BUFFERTAGwillhave*tobefixedtozerothem,sincethisstructisusedasahashkey.*注意:如果在结构体中有填充的字节,INIT_BUFFERTAG必须将它们固定为零,因为这个结构体用作散列键.*/typedefstructbuftag{//物理relation标识符RelFileNodernode;/*physicalrelationidentifier*/ForkNumberforkNum;//相对于relation起始的块号BlockNumberblockNum;/*blknumrelativetobeginofreln*/}BufferTag;

HTAB
哈希表的顶层控制结构.

/**Topcontrolstructureforahashtable---inasharedtable,eachbackend*hasitsowncopy(OKsincenofieldschangeatruntime)*哈希表的顶层控制结构.*在这个共享哈希表中,每一个后台进程都有自己的拷贝*(之所以没有问题是因为fork出来后,在运行期没有字段会变化)*/structHTAB{//指向共享的控制信息HASHHDR*hctl;/*=>sharedcontrolinformation*///段开始目录HASHSEGMENT*dir;/*directoryofsegmentstarts*///哈希函数HashValueFunchash;/*hashfunction*///哈希键比较函数HashCompareFuncmatch;/*keycomparisonfunction*///哈希键拷贝函数HashCopyFunckeycopy;/*keycopyingfunction*///内存分配器HashAllocFuncalloc;/*memoryallocator*///内存上下文MemoryContexthcxt;/*memorycontextifdefaultallocatorused*///表名(用于错误信息)char*tabname;/*tablename(forerrormessages)*///如在共享内存中,则为Tboolisshared;/*trueiftableisinsharedmemory*///如为T,则固定大小不能扩展boolisfixed;/*iftrue,don'tenlarge*//*freezingasharedtableisn'tallowed,sowecankeepstatehere*///不允许冻结共享表,因此这里会保存相关状态boolfrozen;/*true=nomoreinsertsallowed*//*Wekeeplocalcopiesofthesefixedvaluestoreducecontention*///保存这些固定值的本地拷贝,以减少冲突//哈希键长度(以字节为单位)Sizekeysize;/*hashkeylengthinbytes*///段大小,必须为2的幂longssize;/*segmentsize---mustbepowerof2*///段偏移,ssize的对数intsshift;/*segmentshift=log2(ssize)*/};/**Headerstructureforahashtable---containsallchangeableinfo*哈希表的头部结构--存储所有可变信息**Inashared-memoryhashtable,theHASHHDRisinsharedmemory,while*eachbackendhasalocalHTABstruct.Foranon-sharedtable,thereisn't*anyfunctionaldifferencebetweenHASHHDRandHTAB,butweseparatethem*anywaytosharecodebetweensharedandnon-sharedtables.*在共享内存哈希表中,HASHHDR位于共享内存中,每一个后台进程都有一个本地HTAB结构.*对于非共享哈希表,HASHHDR和HTAB没有任何功能性的不同,*但无论如何,我们还是把它们区分为共享和非共享表.*/structHASHHDR{/**Thefreelistcanbecomeapointofcontentioninhigh-concurrencyhash*tables,soweuseanarrayoffreelists,eachwithitsownmutexand*nentriescount,insteadofjustasingleone.Althoughthefreelists*normallyoperateindependently,wewillscavengeentriesfromfreelists*otherthanahashcode'sdefaultfreelistwhennecessary.*在高并发的哈希表中,空闲链表会成为竞争热点,因此我们使用空闲链表数组,*数组中的每一个元素都有自己的mutex和条目统计,而不是使用一个.**Ifthehashtableisnotpartitioned,onlyfreeList[0]isusedandits*spinlockisnotusedatall;callers'lockingisassumedsufficient.*如果哈希表没有分区,那么只有freelist[0]元素是有用的,自旋锁没有任何用处;*调用者锁定被认为已足够OK.*/FreeListDatafreeList[NUM_FREELISTS];/*Thesefieldscanchange,butnotinapartitionedtable*///这些域字段可以改变,但不适用于分区表/*Also,dsizecan'tchangeinasharedtable,evenifunpartitioned*///同时,就算是非分区表,共享表的dsize也不能改变//目录大小longdsize;/*directorysize*///已分配的段大小(<=dbsize)longnsegs;/*numberofallocatedsegments(<=dsize)*///正在使用的最大桶IDuint32max_bucket;/*IDofmaximumbucketinuse*///进入整个哈希表的模掩码uint32high_mask;/*masktomodulointoentiretable*///进入低于半个哈希表的模掩码uint32low_mask;/*masktomodulointolowerhalfoftable*//*Thesefieldsarefixedathashtablecreation*///下面这些字段在哈希表创建时已固定//哈希键大小(以字节为单位)Sizekeysize;/*hashkeylengthinbytes*///所有用户元素大小(以字节为单位)Sizeentrysize;/*totaluserelementsizeinbytes*///分区个数(2的幂),或者为0longnum_partitions;/*#partitions(mustbepowerof2),or0*///目标的填充因子longffactor;/*targetfillfactor*///如目录是固定大小,则该值为dsize的上限值longmax_dsize;/*'dsize'limitifdirectoryisfixedsize*///段大小,必须是2的幂longssize;/*segmentsize---mustbepowerof2*///端偏移,ssize的对数intsshift;/*segmentshift=log2(ssize)*///一次性分配的条目个数intnelem_alloc;/*numberofentriestoallocateatonce*/#ifdefHASH_STATISTICS/**Countstatisticshere.NB:statscodedoesn'tbotherwithmutex,so*countscouldbecorruptedabitinapartitionedtable.*统计信息.*注意:统计相关的代码不会影响mutex,因此对于分区表,统计可能有一点点问题*/longaccesses;longcollisions;#endif};/**Per-freelistdata.*空闲链表数据.**Inapartitionedhashtable,eachfreelistisassociatedwithaspecific*setofhashcodes,asdeterminedbytheFREELIST_IDX()macrobelow.*nentriestracksthenumberoflivehashtableentrieshavingthosehashcodes*(NOTthenumberofentriesinthefreelist,asyoumightexpect).*在一个分区哈希表中,每一个空闲链表与特定的hashcodes集合相关,通过下面的FREELIST_IDX()宏进行定义.*nentries跟踪有这些hashcodes的仍存活的hashtable条目个数.*(注意不要搞错,不是空闲的条目个数)**Thecoverageofafreelistmightbemoreorlessthanonepartition,soit*needsitsownlockratherthanrelyingoncallerlocking.Relyingonthat*wouldn'tworkevenifthecoveragewasthesame,becauseoftheoccasional*needto"borrow"entriesfromanotherfreelist;seeget_hash_entry().*空闲链表的覆盖范围可能比一个分区多或少,因此需要自己的锁而不能仅仅依赖调用者的锁.*依赖调用者锁在覆盖面一样的情况下也不会起效,因为偶尔需要从另一个自由列表“借用”条目,详细参见get_hash_entry()**UsinganarrayofFreeListDatainsteadofseparatearraysofmutexes,*nentriesandfreeListshelpstoreducesharingofcachelinesbetween*differentmutexes.*使用FreeListData数组而不是一个独立的mutexes,nentries和freelists数组有助于减少不同mutexes之间的缓存线共享.*/typedefstruct{//该空闲链表的自旋锁slock_tmutex;/*spinlockforthisfreelist*///相关桶中的条目个数longnentries;/*numberofentriesinassociatedbuckets*///空闲元素链HASHELEMENT*freeList;/*chainoffreeelements*/}FreeListData;/**HASHELEMENTistheprivatepartofahashtableentry.Thecaller'sdata*followstheHASHELEMENTstructure(onaMAXALIGN'dboundary).Thehashkey*isexpectedtobeatthestartofthecaller'shashentrydatastructure.*HASHELEMENT是哈希表条目的私有部分.*调用者的数据按照HASHELEMENT结构组织(位于MAXALIGN的边界).*哈希键应位于调用者hash条目数据结构的开始位置.*/typedefstructHASHELEMENT{//链接到相同桶中的下一个条目structHASHELEMENT*link;/*linktonextentryinsamebucket*///该条目的哈希函数结果uint32hashvalue;/*hashfunctionresultforthisentry*/}HASHELEMENT;/*Hashtableheaderstructisanopaquetypeknownonlywithindynahash.c*///哈希表头部结构,非透明类型,用于dynahash.ctypedefstructHASHHDRHASHHDR;/*Hashtablecontrolstructisanopaquetypeknownonlywithindynahash.c*///哈希表控制结构,非透明类型,用于dynahash.ctypedefstructHTABHTAB;/*Parameterdatastructureforhash_create*///hash_create使用的参数数据结构/*Onlythosefieldsindicatedbyhash_flagsneedbeset*///根据hash_flags标记设置相应的字段typedefstructHASHCTL{//分区个数(必须是2的幂)longnum_partitions;/*#partitions(mustbepowerof2)*///段大小longssize;/*segmentsize*///初始化目录大小longdsize;/*(initial)directorysize*///dsize上限longmax_dsize;/*limittodsizeifdirsizeislimited*///填充因子longffactor;/*fillfactor*///哈希键大小(字节为单位)Sizekeysize;/*hashkeylengthinbytes*///参见上述数据结构注释Sizeentrysize;/*totaluserelementsizeinbytes*///HashValueFunchash;/*hashfunction*/HashCompareFuncmatch;/*keycomparisonfunction*/HashCopyFunckeycopy;/*keycopyingfunction*/HashAllocFuncalloc;/*memoryallocator*/MemoryContexthcxt;/*memorycontexttouseforallocations*///共享内存中的哈希头部结构地址HASHHDR*hctl;/*locationofheaderinsharedmem*/}HASHCTL;/*AhashbucketisalinkedlistofHASHELEMENTs*///哈希桶是HASHELEMENTs链表typedefHASHELEMENT*HASHBUCKET;/*Ahashsegmentisanarrayofbucketheaders*///hashsegment是桶数组typedefHASHBUCKET*HASHSEGMENT;/**Hashfunctionsmusthavethissignature.*Hash函数必须有它自己的标识*/typedefuint32(*HashValueFunc)(constvoid*key,Sizekeysize);/**Keycomparisonfunctionsmusthavethissignature.Comparisonfunctions*returnzeroformatch,nonzerofornomatch.(Thecomparisonfunction*definitionisdesignedtoallowmemcmp()andstrncmp()tobeuseddirectly*askeycomparisonfunctions.)*哈希键对比函数必须有自己的标识.*如匹配则对比函数返回0,不匹配返回非0.*(对比函数定义被设计为允许在对比键值时可直接使用memcmp()和strncmp())*/typedefint(*HashCompareFunc)(constvoid*key1,constvoid*key2,Sizekeysize);/**Keycopyingfunctionsmusthavethissignature.Thereturnvalueisnot*used.(Thedefinitionissetuptoallowmemcpy()andstrlcpy()tobe*useddirectly.)*键拷贝函数必须有自己的标识.*返回值无用.*/typedefvoid*(*HashCopyFunc)(void*dest,constvoid*src,Sizekeysize);/**Spaceallocationfunctionforahashtable---designedtomatchmalloc().*Note:thereisnofreefunctionAPI;can'tdestroyahashtableunlessyou*usethedefaultallocator.*哈希表的恐惧分配函数--被设计为与malloc()函数匹配.*注意:这里没有释放函数API;不能销毁哈希表,除非使用默认的分配器.*/typedefvoid*(*HashAllocFunc)(Sizerequest);

BufferLookupEnt

/*entryforbufferlookuphashtable*///检索hash表的条目typedefstruct{//磁盘page的tagBufferTagkey;/*Tagofadiskpage*///相关联的bufferIDintid;/*AssociatedbufferID*/}BufferLookupEnt;二、源码解读

BufTableInsert源码很简单,重点是需要理解HTAB数据结构,即全局变量SharedBufHash的数据结构.

/**BufTableInsert*InsertahashtableentryforgiventagandbufferID,*unlessanentryalreadyexistsforthattag*BufTableInsert*给定tag和bufferID,插入到哈希表中,如该tag相应的条目已存在,则不处理.**Returns-1onsuccessfulinsertion.Ifaconflictingentryexists*already,returnsthebufferIDinthatentry.*如成功插入,则返回-1.如冲突的条目已存在,则返回条目的bufferID.**CallermustholdexclusivelockonBufMappingLockfortag'spartition*调用者必须持有tag分区BufMappingLock独占锁.*/intBufTableInsert(BufferTag*tagPtr,uint32hashcode,intbuf_id){BufferLookupEnt*result;boolfound;Assert(buf_id>=0);/*-1isreservedfornot-in-table*/Assert(tagPtr->blockNum!=P_NEW);/*invalidtag*///staticHTAB*SharedBufHash;result=(BufferLookupEnt*)hash_search_with_hash_value(SharedBufHash,(void*)tagPtr,hashcode,HASH_ENTER,&found);if(found)/*foundsomethingalreadyinthetable*/returnresult->id;result->id=buf_id;return-1;}三、跟踪分析

测试脚本,查询数据表:

10:01:54(xdb@[local]:5432)testdb=#select*fromt1limit10;

启动gdb,设置断点

(gdb)(gdb)bBufTableInsertBreakpoint1at0x875c92:filebuf_table.c,line125.(gdb)cContinuing.Breakpoint1,BufTableInsert(tagPtr=0x7fff0cba0ef0,hashcode=1398580903,buf_id=101)atbuf_table.c:125125Assert(buf_id>=0);/*-1isreservedfornot-in-table*/(gdb)

输入参数
tagPtr-BufferTag结构体
hashcode=1398580903,
buf_id=101

(gdb)p*tagPtr$1={rnode={spcNode=1663,dbNode=16402,relNode=51439},forkNum=MAIN_FORKNUM,blockNum=0}

调用hash_search_with_hash_value,重点考察SharedBufHash(HTAB指针)

(gdb)n129hash_search_with_hash_value(SharedBufHash,

SharedBufHash

(gdb)p*SharedBufHash$2={hctl=0x7f5489004380,dir=0x7f54890046d8,hash=0xa3bf74<tag_hash>,match=0x4791a0<memcmp@plt>,keycopy=0x479690<memcpy@plt>,alloc=0x89250b<ShmemAllocNoError>,hcxt=0x0,tabname=0x1fbf1d8"SharedBufferLookupTable",isshared=true,isfixed=false,frozen=false,keysize=20,ssize=256,sshift=8}(gdb)

SharedBufHash->hctl,HASHHDR结构体
freeList是一个数组
num_partitions是分区个数,默认为128

(gdb)p*SharedBufHash->hctl$3={freeList={{mutex=0'\000',nentries=3,freeList=0x7f5489119700},{mutex=0'\000',nentries=2,freeList=0x7f548912d828},{mutex=0'\000',nentries=4,freeList=0x7f54891418d8},{mutex=0'\000',nentries=3,freeList=0x7f5489155a00},{mutex=0'\000',nentries=8,freeList=0x7f5489169a38},{mutex=0'\000',nentries=3,freeList=0x7f548917dc00},{mutex=0'\000',nentries=5,freeList=0x7f5489191cb0},{mutex=0'\000',nentries=3,freeList=0x7f54891a5e00},{mutex=0'\000',nentries=1,freeList=0x7f54891b9f50},{mutex=0'\000',nentries=3,freeList=0x7f54891ce000},{mutex=0'\000',nentries=3,freeList=0x7f54891e2100},{mutex=0'\000',nentries=5,freeList=0x7f54891f61b0},{mutex=0'\000',nentries=4,freeList=0x7f548920a2d8},{mutex=0'\000',nentries=2,freeList=0x7f548921e428},{mutex=0'\000',nentries=2,freeList=0x7f5489232528},{mutex=0'\000',nentries=4,freeList=0x7f54892465d8},{mutex=0'\000',nentries=3,freeList=0x7f548925a700},{mutex=0'\000',nentries=3,freeList=0x7f548926e800},{mutex=0'\000',nentries=5,freeList=0x7f54892828b0},{mutex=0'\000',nentries=2,freeList=0x7f5489296a28},{mutex=0'\000',nentries=4,freeList=0x7f54892aaad8},{mutex=0'\000',nentries=4,freeList=0x7f54892bebd8},{mutex=0'\000',nentries=5,freeList=0x7f54892d2cb0},{mutex=0'\000',nentries=0,freeList=0x7f54892e6e78},{mutex=0'\000',nentries=2,freeList=0x7f54892faf28},{mutex=0'\000',nentries=3,freeList=0x7f548930f000},{mutex=0'\000',nentries=4,freeList=0x7f54893230d8},{mutex=0'\000',nentries=4,freeList=0x7f54893371d8},{mutex=0'\000',nentries=2,freeList=0x7f548934b328},{mutex=0'\000',nentries=1,freeList=0x7f548935f450},{mutex=0'\000',nentries=4,freeList=0x7f54893734d8},{mutex=0'\000',nentries=3,freeList=0x7f5489387600}},dsize=512,nsegs=512,max_bucket=131071,high_mask=262143,low_mask=131071,keysize=20,entrysize=24,num_partitions=128,ffactor=1,max_dsize=512,ssize=256,sshift=8,nelem_alloc=51}(gdb)(gdb)p*SharedBufHash->hctl->freeList[0].freeList$4={link=0x7f54891196d8,hashvalue=0}(gdb)p*SharedBufHash->hctl->freeList[0].freeList.link$5={link=0x7f54891196b0,hashvalue=0}(gdb)

SharedBufHash->dir,段开始目录

(gdb)p*SharedBufHash->dir$6=(HASHSEGMENT)0x7f5489005700(gdb)p**SharedBufHash->dir$7=(HASHBUCKET)0x0(gdb)p*SharedBufHash->dir[0]$8=(HASHBUCKET)0x0(gdb)p*SharedBufHash->dir[1]$9=(HASHBUCKET)0x0(gdb)

哈希函数为tag_hash
哈希键比较函数是memcmp@plt
哈希键拷贝函数是memcpy@plt
内存分配器是ShmemAllocNoError
内存上下文为NULL
表名是Shared Buffer Lookup Table
共享内存(isshared=T)
非固定/非冻结/哈希键长度为20B/段大小为256/段偏移为8

执行hash_search_with_hash_value,查看相关信息

(gdb)n128result=(BufferLookupEnt*)(gdb)135if(found)/*foundsomethingalreadyinthetable*/(gdb)p*SharedBufHash$10={hctl=0x7f5489004380,dir=0x7f54890046d8,hash=0xa3bf74<tag_hash>,match=0x4791a0<memcmp@plt>,keycopy=0x479690<memcpy@plt>,alloc=0x89250b<ShmemAllocNoError>,hcxt=0x0,tabname=0x1fbf1d8"SharedBufferLookupTable",isshared=true,isfixed=false,frozen=false,keysize=20,ssize=256,sshift=8}(gdb)p*SharedBufHash->hctl$11={freeList={{mutex=0'\000',nentries=3,freeList=0x7f5489119700},{mutex=0'\000',nentries=2,freeList=0x7f548912d828},{mutex=0'\000',nentries=4,freeList=0x7f54891418d8},{mutex=0'\000',nentries=3,freeList=0x7f5489155a00},{mutex=0'\000',nentries=8,freeList=0x7f5489169a38},{mutex=0'\000',nentries=3,freeList=0x7f548917dc00},{mutex=0'\000',nentries=5,freeList=0x7f5489191cb0},{mutex=0'\000',nentries=4,freeList=0x7f54891a5dd8},{mutex=0'\000',nentries=1,freeList=0x7f54891b9f50},{mutex=0'\000',nentries=3,freeList=0x7f54891ce000},{mutex=0'\000',nentries=3,freeList=0x7f54891e2100},{mutex=0'\000',nentries=5,freeList=0x7f54891f61b0},{mutex=0'\000',nentries=4,freeList=0x7f548920a2d8},{mutex=0'\000',nentries=2,freeList=0x7f548921e428},{mutex=0'\000',nentries=2,freeList=0x7f5489232528},{mutex=0'\000',nentries=4,freeList=0x7f54892465d8},{mutex=0'\000',nentries=3,freeList=0x7f548925a700},{mutex=0'\000',nentries=3,freeList=0x7f548926e800},{mutex=0'\000',nentries=5,freeList=0x7f54892828b0},{mutex=0'\000',nentries=2,freeList=0x7f5489296a28},{mutex=0'\000',nentries=4,freeList=0x7f54892aaad8},{mutex=0'\000',nentries=4,freeList=0x7f54892bebd8},{mutex=0'\000',nentries=5,freeList=0x7f54892d2cb0},{mutex=0'\000',nentries=0,freeList=0x7f54892e6e78},{mutex=0'\000',nentries=2,freeList=0x7f54892faf28},{mutex=0'\000',nentries=3,freeList=0x7f548930f000},{mutex=0'\000',nentries=4,freeList=0x7f54893230d8},{mutex=0'\000',nentries=4,freeList=0x7f54893371d8},{mutex=0'\000',nentries=2,freeList=0x7f548934b328},{mutex=0'\000',nentries=1,freeList=0x7f548935f450},{mutex=0'\000',nentries=4,freeList=0x7f54893734d8},{mutex=0'\000',nentries=3,freeList=0x7f5489387600}},dsize=512,nsegs=512,max_bucket=131071,high_mask=262143,low_mask=131071,keysize=20,entrysize=24,num_partitions=128,ffactor=1,max_dsize=512,ssize=256,sshift=8,nelem_alloc=51}(gdb)p**SharedBufHash->dir$12=(HASHBUCKET)0x0(gdb)p*SharedBufHash->dir$13=(HASHSEGMENT)0x7f5489005700(gdb)presult$14=(BufferLookupEnt*)0x7f54891a5e10(gdb)p*result$15={key={rnode={spcNode=1663,dbNode=16402,relNode=51439},forkNum=MAIN_FORKNUM,blockNum=0},id=0}(gdb)pfound$16=false

完成调用,返回

(gdb)n138result->id=buf_id;(gdb)140return-1;(gdb)141}(gdb)BufferAlloc(smgr=0x204f430,relpersistence=112'p',forkNum=MAIN_FORKNUM,blockNum=0,strategy=0x0,foundPtr=0x7fff0cba0fa3)atbufmgr.c:12161216if(buf_id>=0)(gdb)

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