欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PostgreSQL如何查看事務(wù)所占有的鎖實(shí)操指南

 更新時(shí)間:2023年10月24日 15:35:00   作者:賈欣曉  
這篇文章主要給大家介紹了關(guān)于PostgreSQL如何查看事務(wù)所占有鎖的相關(guān)資料,文中通過代碼以及圖文介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用PostgreSQL具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

表級鎖命令LOCK TABLE

在PG中,顯式地在表上加鎖的命令為“LOCK TABLE”,此命令的語法如下:

LOCK [TABLE] [ONLY] name [,...][IN lockmode MODE] [NOWAIT]

語法中各項(xiàng)參數(shù)說明如下:

  • name:表名
  • lockmode:表級鎖模式,即SHARE、EXCLUSIVE、ACCESS SHARE、ACCESS EXCLUSIVE、ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE ROW EXCLUSIVE
  • NOWAIT:如果沒有NOWAIT這個(gè)關(guān)鍵字,當(dāng)無法獲得鎖時(shí)會一直等待,而如果加了NOWAIT關(guān)鍵字,在無法立即獲取該鎖時(shí),此命令會立即退出并且報(bào)錯

在PG中,事務(wù)自己的鎖是從不沖突的,因此一個(gè)事務(wù)可以在持有SHARE模式的鎖時(shí)再請求ROW EXCLUSIVE鎖,而不會出現(xiàn)自己的鎖阻塞自己的情況。

當(dāng)事務(wù)要更新表中的數(shù)據(jù)時(shí),應(yīng)該申請ROW EXCLUSIVE鎖,而不應(yīng)該申請SHARE鎖,因?yàn)樵诟聰?shù)據(jù)時(shí),事務(wù)還是會對表加ROW EXCLUSIVE鎖,想象一下,在兩個(gè)并發(fā)的事務(wù)都請求SHARE鎖后,開始更新數(shù)據(jù)前要對表加ROW EXCLUSIVE鎖,但由于各自先前已加了SHARE鎖,所以都要等待對方釋放SHARE鎖,因而出現(xiàn)死鎖。從這個(gè)示例可以看出,如果涉及多種鎖模式,那么事務(wù)應(yīng)該總是最先請求最嚴(yán)格的鎖模式,否則就容易出現(xiàn)死鎖。

行級鎖命令

顯式的行級鎖命令是由SELECT命令后加如下子句來構(gòu)成的:

SELECT ... FOR {UPDATE | SHARE} [OF table_name [,...]] [NOWAIT] [...]

  • NOWAIT關(guān)鍵字加上,如果無法獲得鎖則直接報(bào)錯,而不會一直等待。
  • OF table_name明確指定表名字,那么只有被指定的表會被鎖定,其他在SELECT中使用的表則不會
  • 不帶OF table_name的FOR UPDATE或者FOR SHARE子句將鎖定該命令中使用的所有表
  • 如果FOR UPDATE或者FOR SHARE應(yīng)用于一個(gè)視圖或者子查詢,那么它將同樣鎖定該視圖或者子查詢中使用到的所有表
  • 主查詢中引用了WITH查詢時(shí),WITH查詢中的表并不會被鎖定
  • 如果想要鎖定WITH查詢內(nèi)的表行,需要在WITH查詢內(nèi)指定FOR UPDATE或者FOR SHARE關(guān)鍵字

鎖的查看

我們經(jīng)常需要查看一個(gè)事務(wù)產(chǎn)生了哪些鎖,哪個(gè)事務(wù)被哪個(gè)事務(wù)阻塞了,若執(zhí)行一條SQL語句時(shí)阻塞住了,需要查詢?yōu)槭裁醋枞?,是誰阻塞住的,這些信息可以通過查詢系統(tǒng)視圖“pg_locks”來得到。pg_locks視圖中各列的描述如下:

列名稱列類型引用描述
locktypetext被鎖定的對象類型:relation、extend、page、tuple、transactionid、virtualxid、object、userlock、advisory
databaseoidpg_database.oid鎖定對象的數(shù)據(jù)庫OID,如果對象是一個(gè)共享對象,不屬于任何數(shù)據(jù)庫,此值為“0”,如果對象是“transaction ID”,此值為空
relationoidpg_class.oid如果對象不是表或只是表的一部分,則此值為“NULL”,否則此值是表的OID
pageinteger表中的頁號,如果對象不是表行(tuple)或表頁(relation page),則此值為“NULL”
tuplesmallint頁內(nèi)的行號(tuple)
virtualxidtext虛擬事務(wù)id
transactionidxid事務(wù)id
classidoidpg_class.oid包含該對象系統(tǒng)目錄的id
objidoidany OID column對象在系統(tǒng)目錄的oid
objsubidsmallint如果對象是表列(table column),此列的值為列號,這時(shí)classid和objid指向表
virtualtransactiontext持有或等待這把鎖的虛擬事務(wù)id
pidinteger持有或等待這把鎖的服務(wù)進(jìn)程的PID,如果此鎖是被一個(gè)兩階段提交的事務(wù)持有,則此值為NULL
modetext鎖的模式名稱,如“ACCESS SHARE”“SHARE”“EXCLUSIVE”等鎖模式
grantedboolean如果鎖已被持有,此值為True,如果等待獲得此鎖,則此值為False

上述中,描述事務(wù)id的字段有三個(gè):

  • virtualxid
  • transactionid
  • virtualtransaction
  1. transactionid代表事務(wù)id,簡寫為“xid”
  2. virtualxid代表虛擬事務(wù)id,簡寫為“vxid”
  3. 每產(chǎn)生一個(gè)事務(wù)id,都會在pg_clog下的commit log文件中占用2bit
  4. 最早pg中本沒有虛擬事務(wù)id,但是后來發(fā)現(xiàn),有一些事務(wù)根本沒有產(chǎn)生任何實(shí)質(zhì)的變更,如一個(gè)只讀事務(wù)或一個(gè)空事務(wù),若在這種情況下也分配一個(gè)事務(wù)id會造成浪費(fèi),于是提出了虛擬事務(wù)id的概念
  5. 對于這類只讀事務(wù),值分配一個(gè)虛擬事務(wù)id,而不是實(shí)際分配一個(gè)真實(shí)的事務(wù)id,這樣就不需要在commit log中占用2bit的空間了

pg_locks這張視圖的字段分為以下兩部分:

  • virtualtransaction之前的字段(不包括virtualtransaction字段),我們稱其為“第一部分”,用于描述鎖定對象(Locked Object)信息
  • virtualtransaction之后的字段(包括virtualtransaction字段),我們稱其為“第二部分”,用于描述持有鎖或等待鎖的session信息

了解上述概念后,可以容易理解virtualxid和virtualtransaction兩個(gè)字段的意思:

  • virtualxid在第一部分字段中,表示鎖對象是一個(gè)virtualxid
  • virtualtransaction表示持有鎖或等待鎖session的虛擬事務(wù)id

表鎖實(shí)操

1.先開一個(gè)psql窗口,命令如下:

image

第一個(gè)窗口,查詢PID,并鎖定一張表。

2.第二個(gè)窗口中查看數(shù)據(jù)庫中的鎖的情況:

image

sql命令:

select locktype,relation::regclass as rel,virtualxid as vxid,transactionid as xid,virtualtransaction as vxid2,pid,mode,granted from pg_locks where pid = 12264;

通過上述圖片可以看出:

  • 第一行顯示的是事務(wù)在自己的“virtualxid”上加的ExclusiveLock鎖,這是必定會加上的
  • 第二行才是我們實(shí)際在表上加的鎖“AccessExclusiveLock”

3.新增一個(gè)窗口,顯示地對表加鎖:

image

執(zhí)行sql語句發(fā)現(xiàn),該窗口的鎖表語句會被阻塞住

4.查看兩個(gè)進(jìn)程的鎖情況:

image

  • 發(fā)現(xiàn)兩個(gè)進(jìn)程都對表加了鎖
  • 進(jìn)程12264中的granted字段為t,說明它獲得了這把鎖
  • 進(jìn)程21052中的granted字段為f,說明該進(jìn)程沒有獲得這把鎖,從而被阻塞

行鎖實(shí)操

1.第一個(gè)窗口執(zhí)行如下操作(在加表鎖的基礎(chǔ)上加行鎖):

image

2.第二個(gè)窗口中查看數(shù)據(jù)庫中的鎖的情況:

image

行鎖不僅會在表上加意向鎖,也會在相應(yīng)的主鍵上加意向鎖。其中“jxx_test_pkey”就是表的主鍵。

3.另一個(gè)窗口加行鎖:

image

該窗口阻塞

4.第二個(gè)窗口中查看數(shù)據(jù)庫中的鎖的情況:

image

xid為739的鎖被進(jìn)程12264持有了,所以21052的進(jìn)程獲取鎖標(biāo)識為False

5.如何查看具體是哪一行數(shù)據(jù)被阻塞

-- 其中0和1分別代表pg_locks中的page和tuple字段
select * from jxx_test where ctid = '(0,1)'

pg_locks并不能顯示出每個(gè)行鎖的信息,因?yàn)樾墟i信息并不會被記錄到共享內(nèi)存中。如果記錄到內(nèi)存,意味著對表做全表更新時(shí),表有多少行就需要在內(nèi)存中記錄多少條行鎖信息,那么內(nèi)存會吃不消,所以postgreSQL設(shè)計(jì)成不在內(nèi)存中記錄行鎖信息。

思考:如何獲取進(jìn)程是在哪一行上被阻塞的?

總結(jié)

到此這篇關(guān)于PostgreSQL如何查看事務(wù)所占有的鎖的文章就介紹到這了,更多相關(guān)PostgreSQL查看事務(wù)所占有鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論