當多個會話同時訪問數據庫的同一數據時,理想狀態是為所有會話提供高效的訪問,同時還要維護嚴格的數據一致性。那這數據一致性通過什么來維護呢?就是之前文章多次提到的MVCC(多版本并發控制),可以點擊下列文章標題回顧早前發布的內容:
PostgreSQL提供了多種鎖模式用于控制對表中數據的并發訪問,其中最主要的是表級鎖與行級鎖,此外還有頁級鎖,咨詢鎖等等,接下來主要介紹表級鎖與行級鎖。
通過上面2個案例我們應該比較了解各種鎖模式沖突的情況了。接下來我們介紹行級鎖。
鎖目標存在的數據庫的OID,如果目標是一個共享對象則為0,如果目標是一個事務ID則為空。
作為鎖目標的關系的OID,如果目標不是一個關系或者只是關系的一部分則此列為空。
作為鎖目標的頁在關系中的頁號,如果目標不是一個關系頁或元組則此列為空。
作為鎖目標的元組在頁中的元組號,如果目標不是一個元組則此列為空。
作為鎖目標的事務虛擬ID,如果目標不是一個虛擬事務ID則此列為空。
作為鎖目標的事務ID,如果目標不是一個事務ID則此列為空ID。
包含鎖目標的系統目錄的OID,如果目標不是一個普通數據庫對象則此列為空。
鎖目標在它的系統目錄中的OID,如果目標不是一個普通數據庫對象則為空。
鎖的目標列號(classid和objid指表本身),如果目標是某種其他普通數據庫對象則此列為0,如果目標不是一個普通數據庫對象則此列為空。
保持這個鎖或者正在等待這個鎖的事務的虛擬ID。
保持這個鎖或者正在等待這個鎖的服務器進程的PID,如果此鎖被一個預備事務所持有則此列為空。
此進程已持有或者希望持有的鎖模式的名稱。
如果鎖已授予則為真,如果鎖被等待則為假。
with
t_wait as
(
select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,
b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name
from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted
),
t_run as
(
select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.granted,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,a.transactionid,a.fastpath,
b.state,b.query,b.xact_start,b.query_start,b.usename,b.datname,b.client_addr,b.client_port,b.application_name
from pg_locks a,pg_stat_activity b where a.pid=b.pid and a.granted
),
t_overlap as
(
select r.* from t_wait w join t_run r on
(
r.locktype is not distinct from w.locktype and
r.database is not distinct from w.database and
r.relation is not distinct from w.relation and
r.page is not distinct from w.page and
r.tuple is not distinct from w.tuple and
r.virtualxid is not distinct from w.virtualxid and
r.transactionid is not distinct from w.transactionid and
r.classid is not distinct from w.classid and
r.objid is not distinct from w.objid and
r.objsubid is not distinct from w.objsubid and
r.pid <> w.pid
)
),
t_unionall as
(
select r.* from t_overlap r
union all
select w.* from t_wait w
)
select locktype,datname,relation::regclass,page,tuple,virtualxid,transactionid::text,classid::regclass,objid,objsubid,
string_agg(
Pid: ||case when pid is null then NULL else pid::text end||chr(10)||
Lock_Granted: ||case when granted is null then NULL else granted::text end|| , Mode: ||case when mode is null then NULL else mode::text end|| , FastPath: ||case when fastpath is null then NULL else fastpath::text end|| , VirtualTransaction: ||case when virtualtransaction is null then NULL else virtualtransaction::text end|| , Session_State: ||case when state is null then NULL else state::text end||chr(10)||
Username: ||case when usename is null then NULL else usename::text end|| , Database: ||case when datname is null then NULL else datname::text end|| , Client_Addr: ||case when client_addr is null then NULL else client_addr::text end|| , Client_Port: ||case when client_port is null then NULL else client_port::text end|| , Application_Name: ||case when application_name is null then NULL else application_name::text end||chr(10)||
Xact_Start: ||case when xact_start is null then NULL else xact_start::text end|| , Query_Start: ||case when query_start is null then NULL else query_start::text end|| , Xact_Elapse: ||case when (now()-xact_start) is null then NULL else (now()-xact_start)::text end|| , Query_Elapse: ||case when (now()-query_start) is null then NULL else (now()-query_start)::text end||chr(10)||
SQL (Current SQL in Transaction): ||chr(10)||
case when query is null then NULL else query::text end,
chr(10)||--------||chr(10)
order by
( case mode
when INVALID then 0
when AccessShareLock then 1
when RowShareLock then 2
when RowExclusiveLock then 3
when ShareUpdateExclusiveLock then 4
when ShareLock then 5
when ShareRowExclusiveLock then 6
when ExclusiveLock then 7
when AccessExclusiveLock then 8
else 0
end ) desc,
(case when granted then 0 else 1 end)
) as lock_conflict
from t_unionall
group by
locktype,datname,relation,page,tuple,virtualxid,transactionid::text,classid,objid,objsubid ;
with recursive tmp_lock as (
select distinct
--w.mode w_mode,w.page w_page,
--w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start,
--now()-w.query_start w_locktime,w.query w_query
w.pid as id,--w_pid,
r.pid as parentid--r_pid,
--r.locktype,r.mode r_mode,r.usename r_user,r.datname r_db,
--r.relation::regclass,
--r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start,
--r.query_start r_query_start,
--now()-r.query_start r_locktime,r.query r_query,
from (
select a.mode,a.locktype,a.database,
a.relation,a.page,a.tuple,a.classid,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,
a.transactionid,
b.query as query,
b.xact_start,b.query_start,b.usename,b.datname
from pg_locks a,
pg_stat_activity b
where a.pid=b.pid
and not a.granted
) w,
(
select a.mode,a.locktype,a.database,
a.relation,a.page,a.tuple,a.classid,
a.objid,a.objsubid,a.pid,a.virtualtransaction,a.virtualxid,
a.transactionid,
b.query as query,
b.xact_start,b.query_start,b.usename,b.datname
from pg_locks a,
pg_stat_activity b -- select pg_typeof(pid) from pg_stat_activity
where a.pid=b.pid
and a.granted
) r
where 1=1
and r.locktype is not distinct from w.locktype
and r.database is not distinct from w.database
and r.relation is not distinct from w.relation
and r.page is not distinct from w.page
and r.tuple is not distinct from w.tuple
and r.classid is not distinct from w.classid
and r.objid is not distinct from w.objid
and r.objsubid is not distinct from w.objsubid
and r.transactionid is not distinct from w.transactionid
and r.pid <> w.pid
),tmp0 as (
select *
from tmp_lock tl
union all
select t1.parentid,0::int4
from tmp_lock t1
where 1=1
and t1.parentid not in (select id from tmp_lock)
),tmp3 (pathid,depth,id,parentid) as (
SELECT array[id]::text[] as pathid,1 as depth,id,parentid
FROM tmp0
where 1=1
and parentid=0
union
SELECT t0.pathid||array[t1.id]::text[] as pathid,t0.depth+1 as depth,t1.id,t1.parentid
FROM tmp0 t1,
tmp3 t0
where 1=1
and t1.parentid=t0.id
)
select distinct
/||array_to_string(a0.pathid,/) as pathid,
a0.depth,
a0.id,a0.parentid,lpad(a0.id::text, 2*a0.depth-1+length(a0.id::text), ) as tree_id,
--select pg_cancel_backend(||a0.id|| ); as cancel_pid,
--select pg_terminate_backend(||a0.id|| ); as term_pid,
case when a0.depth =1 then select pg_terminate_backend(|| a0.id || ); else null end as term_pid,
case when a0.depth =1 then select cancel_backend(|| a0.id || ); else null end as cancel_pid
,a2.datname,a2.usename,a2.application_name,a2.client_addr,a2.wait_event_type,a2.wait_event,a2.state
--,a2.backend_start,a2.xact_start,a2.query_start
from tmp3 a0
left outer join (select distinct /||id||/ as prefix_id,id
from tmp0
where 1=1 ) a1
on position( a1.prefix_id in /||array_to_string(a0.pathid,/)||/ ) >0
left outer join pg_stat_activity a2 -- select * from pg_stat_activity
on a0.id = a2.pid
order by /||array_to_string(a0.pathid,/),a0.depth;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/129295.html
摘要:由此可見,自旋鎖和各有優劣,他們分別適用于競爭不多和競爭激烈的場景中。每一個試圖進入同步代碼塊的線程都會被封裝成對象,它們或在對象的中,或在中,等待成為對象的成為的對象即獲取了監視器鎖。 前言 系列文章目錄 前面兩篇文章我們介紹了synchronized同步代碼塊以及wait和notify機制,大致知道了這些關鍵字和方法是干什么的,以及怎么用。 但是,知其然,并不知其所以然。 例如...
摘要:刪除在使用實現分布式鎖的時候,主要就會使用到這三個命令。其實,使用的可靠性是要大于使用實現的分布式鎖的,但是相比而言,的性能更好。 選用Redis實現分布式鎖原因 Redis有很高的性能 Redis命令對此支持較好,實現起來比較方便 使用命令介紹 SETNX SETNX key val當且僅當key不存在時,set一個key為val的字符串,返回1;若key存在,則什么都不做,返回...
摘要:創建測試表會話一備注會話一在事務里更新的記錄,并不提交。會話二備注會話二刪除的記錄,此時由于這條記錄之前被并沒有提交,這句仍然處于等待狀態。 PosttgreSQL 的SQL被鎖情況在數據庫維護過程中非常常見,之前博客 PostgreSQL 鎖分析 演示了 PostgreSQL 鎖的一些場景,在開始本文的介紹之前特做以下說明,假如會話A堵住會話B,我們稱會話B為 blocked 會話...
閱讀 1346·2023-01-11 13:20
閱讀 1684·2023-01-11 13:20
閱讀 1132·2023-01-11 13:20
閱讀 1858·2023-01-11 13:20
閱讀 4100·2023-01-11 13:20
閱讀 2704·2023-01-11 13:20
閱讀 1385·2023-01-11 13:20
閱讀 3597·2023-01-11 13:20