PostgreSQL模擬兩個update語句死鎖-利用掃描方法
標籤
PostgreSQL , 死鎖 , update , 模擬
背景
在單條UPDATE中模擬死鎖,需要藉助掃描方法,以及明確讓AB兩個會話分別鎖定一條記錄後再鎖定對方已經鎖定的記錄。
利用批量update的語法以及values子句即可實現,這裡利用了巢狀迴圈,確保被更新的表被多次掃描,並且每次掃描時兩個會話更新的記錄被錯開,達到死鎖效果。
同時為了讓速度慢下來,使用pg_sleep函式,讓每一條更新都放緩1秒。
例子
1、建表
postgres=# create table a (id int primary key, info timestamp);
CREATE TABLE
2、寫入測試資料
postgres=# insert into a select generate_series(1,10);
INSERT 0 10
3、會話1 SQL,執行計劃
先鎖定ID=2的記錄,然後鎖定ID=1的記錄。
postgres=# explain update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;
QUERY PLAN
-----------------------------------------------------------------------------
Update on a (cost=0.15..4.80 rows=2 width=46)
-> Nested Loop (cost=0.15..4.80 rows=2 width=46)
Join Filter: (pg_sleep(`1`::double precision) IS NOT NULL) -- 放緩1秒
-> Values Scan on "*VALUES*" (cost=0.00..0.03 rows=2 width=32) -- 按values寫的順序掃描
-> Index Scan using a_pkey on a (cost=0.15..2.37 rows=1 width=10) -- 先更新2,再更新1
Index Cond: (id = "*VALUES*".column1)
(6 rows)
4、會話2 SQL,執行計劃,與會話1相反。
先鎖定ID=1的記錄,然後鎖定ID=2的記錄。
postgres=# explaIN update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;
QUERY PLAN
-----------------------------------------------------------------------------
Update on a (cost=0.15..4.80 rows=2 width=46)
-> Nested Loop (cost=0.15..4.80 rows=2 width=46)
Join Filter: (pg_sleep(`1`::double precision) IS NOT NULL) -- 放緩1秒
-> Values Scan on "*VALUES*" (cost=0.00..0.03 rows=2 width=32) -- 按values寫的順序掃描
-> Index Scan using a_pkey on a (cost=0.15..2.37 rows=1 width=10) -- 先更新1,再更新2
Index Cond: (id = "*VALUES*".column1)
(6 rows)
5、模擬死鎖
會話1
postgres=# update a set info=clock_timestamp() from (values (2),(1)) t(id) where a.id=t.id and pg_sleep(1) is not null;
ERROR: deadlock detected
DETAIL: Process 19893 waits for ShareLock on transaction 18613573; blocked by process 9910.
Process 9910 waits for ShareLock on transaction 18613572; blocked by process 19893.
HINT: See server log for query details.
CONTEXT: while updating tuple (0,1) in relation "a"
馬上發起會話2
postgres=# update a set info=clock_timestamp() from (values (1),(2)) t(id) where a.id=t.id and pg_sleep(1) is not null;
UPDATE 2
相關文章
- PostgreSQL掃描方法綜述SQL
- 簡單模擬死鎖
- 模擬SQLserver死鎖現象SQLServer
- 面試官:請用SQL模擬一個死鎖面試SQL
- 理解資料庫掃描方法-利用掃描方法對資料儲存進行優化資料庫優化
- Oracle vs PostgreSQL,研發注意事項(13) - UPDATE語句OracleSQL
- MySQL insert on duplicate key update 死鎖MySql
- PostgreSQL 死鎖異常SQL
- PostgreSQL死鎖相關SQL
- 一個UPDATE語句引發的血案
- SQLSERVER 語句交錯引發的死鎖研究SQLServer
- 【SQL】10 SQL UPDATE 語句SQL
- PostgreSQL技術內幕(七)索引掃描SQL索引
- Mysql 兩階段鎖和死鎖MySql
- Jtti:MySQL 資料庫中update語句會不會發生死鎖JttiMySql資料庫
- MySQL -update語句流程總結MySql
- ORACLE多表關聯UPDATE語句Oracle
- MySQL的update語句避坑MySql
- PostgreSQL 跟蹤checkpointer出現死鎖SQL
- Sqlserver、oracle中Merge的使用方法,一個merge語句搞定多個Insert,Update,Delete操作SQLServerOracledelete
- 電腦掃描檔案怎麼掃描 win10電腦掃描檔案方法介紹Win10
- 記一次 MySQL select for update 死鎖問題MySql
- SQLite語句(二):INSERT DELETE UPDATE SELECTSQLitedelete
- sipp模擬uas傳送update
- GO語言 實現埠掃描Go
- 一條update語句到底加了多少鎖?帶你深入理解底層原理
- DBeaver如何生成select,update,delete,insert語句delete
- ORA-00060: Deadlock detected 模擬死鎖產生與解決方案
- 兩個看似奇怪的MySQL語句問題MySql
- PostgreSQL大表掃描策略-BAS_BULKREAD,synchronize_seqscansSQL
- AWVS掃描器掃描web漏洞操作Web
- 全表掃描和全索引掃描索引
- Win10系統下掃描器程式無法掃描的解決方法Win10
- RustScan: 能在3秒內掃描65k個埠的Rust掃描工具Rust
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- 掃描器的存在、奧普 掃描器
- KunlunDB功能之insert/update/delete...returning語句delete
- 利用 SonarScanner 靜態掃描 Rainbond 上的 Maven 專案AIMaven