PostgreSql Lock鎖


內容摘自:http://blog.sina.com.cn/s/blog_79d599dc0100qpos.html

上一篇里面提到了PG里面的事務控制級別,是因為上午的一個應用程序跑的過程中,死在DELETE語句部分,查了半天原來是鎖的原因。
下面把查的過程簡單說明一下。
 
首先應用掛起在DELETE語句部分,先查一下DELETE的表數據量,發現只有3K多行,這么小的表應該很快跑完才對。猜想應該是表被鎖住導致操作不能進行下去。於是通過下面的語句查詢是否該表上存在鎖:
SQL:
select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname
from pg_locks a
join pg_class b on a.relation = b.oid
where upper(b.relname) = 'TABLE_NAME';
 
以上為查詢某表上是否存在鎖的SQL語句。
查到后發現確實存在鎖,如下:
 locktype | database |  pid  |      mode       | relation | relname
----------+----------+-------+-----------------+----------+---------
 relation |   439791 | 26752 | AccessShareLock |  2851428 |table_name
 relation |   439791 | 26752 | ExclusiveLock   |  2851428 |table_name
 
再根據上面查出來的pid去表pg_stat_activity查詢一下該鎖對應的SQL語句:
select usename,current_query ,query_start,procpid,client_addr from pg_stat_activity where procpid=26675;
如下:
  usename  |  current_query                      |          query_start         | procpid |  client_addr   
-----------+---------------------------------------------------------------------------------------------------------------+-------------------------------+---------+----------------
 gpcluster | DELETE FROM TABLE_NAME WHERE A = 1  | 2011-05-14 09:35:47.721173+08 |   26752 | 192.168.165.18
(1 row)
 
 
通過以上可以發現,就是上面的鎖導致該語句一直掛在那里。然后把該鎖結束掉后,應用很快跑完。
然后核查應用的代碼,發現代碼里面兩個事務都沒有提交操作。后增加提交操作后,重新跑數,很快跑完。
 
總結:
1、查詢表是否存在鎖postgreSQL的SQL為:
select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname
from pg_locks a
join pg_class b on a.relation = b.oid
where upper(b.relname) = 'TABLE_NAME';
 
2、查詢表鎖及操作的SQL語句的SQL為:
select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname,c.usename,c.current_query,c.query_start,c.client_addr
from pg_locks a
join pg_class b on a.relation = b.oid
join pg_stat_activity c on a.pid = c.procpid
where upper(b.relname) = 'TABLE_NAME';
 
3、對於PG里面的鎖的相關介紹,詳細見:http://cs.scu.edu.cn/~zuojie/pgsqldoc-8.2c/explicit-locking.html
不管是做應用開發,還是平時的基礎數據庫操作的時候,鎖都是得必須注意的一個事情。
 
下面附上PG的表級鎖簡單介紹:
下面的列表顯示了可用的鎖模式和它們被 PostgreSQL 自動使用的場合。你也可以用 LOCK 命令明確獲取這些鎖。請注意所有這些鎖模式都是表級鎖,即使它們的名字包含"row"單詞(這些名稱是歷史遺產)。從某種角度而言,這些名字反應了每種鎖模式的典型用法,但是語意卻都是一樣的。兩種鎖模式之間真正的區別是它們有着不同的沖突鎖集合。兩個事務在同一時刻不能在同一個表上持有相互沖突的鎖。不過,一個事務決不會和自身沖突。比如,它可以在一個表上請求 ACCESS EXCLUSIVE 然后接着請求 ACCESS SHARE 。非沖突鎖模式可以被許多事務同時持有。請特別注意有些鎖模式是自沖突的(比如,在任意時刻 ACCESS EXCLUSIVE 模式就不能夠被多個事務擁有),但其它鎖模式都不是自沖突的(比如,ACCESS SHARE 可以被多個事務持有)。
 
表級鎖模式
 
ACCESS SHARE
只與 ACCESS EXCLUSIVE 沖突。
 
SELECT 命令在被引用的表上請求一個這種鎖。通常,任何只讀取表而不修改它的命令都請求這種鎖模式。
 
ROW SHARE
與 EXCLUSIVE 和 ACCESS EXCLUSIVE 沖突。
 
SELECT FOR UPDATE 和 SELECT FOR SHARE 命令在目標表上需要一個這樣模式的鎖(加上在所有被引用但沒有 ACCESS SHARE 的表上的 FOR UPDATE/FOR SHARE 鎖)。
 
ROW EXCLUSIVE
與 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 沖突。
 
UPDATE, DELETE, INSERT 命令自動請求這個鎖模式(加上所有其它被引用的表上的 ACCESS SHARE 鎖)。通常,這種鎖將被任何修改表中數據的查詢請求。
 
SHARE UPDATE EXCLUSIVE
與 SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 沖突。這個模式保護一個表不被並發模式改變和 VACUUM 。
 
VACUUM(不帶 FULL選項), ANALYZE, CREATE INDEX CONCURRENTLY 請求這樣的鎖。
 
SHARE
與 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 沖突。這個模式避免表的並發數據修改。
 
CREATE INDEX(不帶 CONCURRENTLY 選項)語句要求這樣的鎖模式。
 
SHARE ROW EXCLUSIVE
與 ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 沖突。
 
任何 PostgreSQL 命令都不會自動請求這個鎖模式。
 
EXCLUSIVE
與 ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE 沖突。這個模式只允許並發 ACCESS SHARE 鎖,也就是說,只有對表的讀動作可以和持有這個鎖模式的事務並發執行。
 
任何 PostgreSQL 命令都不會在用戶表上自動請求這個鎖模式。不過,在某些操作的時候,會在某些系統表上請求它。
 
ACCESS EXCLUSIVE
與與所有模式沖突(包括其自身)。這個模式保證其所有者(事務)是可以訪問該表的唯一事務。
 
ALTER TABLE, DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL 命令要求這樣的鎖。在 LOCK TABLE 命令沒有明確聲明需要的鎖模式時,它是缺省鎖模式。
 
【提示】只有 ACCESS EXCLUSIVE 阻塞 SELECT(不包含 FOR UPDATE/SHARE 語句)。
 
一旦請求已獲得某種鎖,那么該鎖模式將持續到事務結束。但是如果在建立保存點之后才獲得鎖,那么在回滾到這個保存點的時候將立即釋放所有該保存點之后獲得的鎖。這與 ROLLBACK 取消所有保存點之后對表的影響的原則一致。同樣的原則也適用於 PL/pgSQL 異常塊中獲得的鎖:一個跳出塊的錯誤將釋放在塊中獲得的鎖。

 

 數據庫查詢語句:

表名稱:

  • 庫表 -> pg_database  //查詢所有數據庫名稱
  • 鎖表 -> pg_locks   //查詢所有鎖名稱
  • 鎖關聯表名->pg_class //realname關聯,查詢鎖關聯的表名,如外部表
  • 鎖-查詢語句->pg_stat_activity //查看每個鎖關聯的查詢語句,起始時間

1,查看數據庫

select  pg_database.datname, pg_database_size(pg_database.datname) AS size from pg_database; //查詢所有數據庫,及其所占空間大小

2. 查詢存在鎖的數據表

select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname -- ,sa.*
from pg_locks a
join pg_class b on a.relation = b.oid 
inner join  pg_stat_activity sa on a.pid=sa.procpid

3.查詢某個表內,狀態為lock的鎖及關聯的查詢語句

select a.locktype,a.database,a.pid,a.mode,a.relation,b.relname -- ,sa.*
from pg_locks a
join pg_class b on a.relation = b.oid 
inner join  pg_stat_activity sa on a.pid=sa.procpid
where a.database=382790774  and sa.waiting_reason='lock'
order by sa.query_start

4.查看數據庫表大小

select pg_database_size('playboy'); 

 

參考資料:

https://www.postgresql.org/docs/9.4/view-pg-locks.html

https://www.yiibai.com/postgresql/postgresql_locks.html

https://my.oschina.net/liuyuanyuangogo/blog/499460

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM