創(chuàng)建表:
CREATE TABLE db_user
(
id character varying(50) NOT NULL,
age integer,
name character varying(100),
roleid character varying,
CONSTRAINT db_user_pkey PRIMARY KEY (id)
)
隨便插入幾條數(shù)據(jù)即可。
一、不加鎖演示
1、打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi';
輸出結(jié)果:
2、再打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi';
輸出結(jié)果:
二、加鎖演示(for update)
1、打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi' for update;
輸出結(jié)果:
2、再打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi' for update;
輸出結(jié)果:
查詢一直處于執(zhí)行中狀態(tài)。
3、第一個(gè)窗口執(zhí)行:
commit;
第二個(gè)窗口立即執(zhí)行查詢操作,結(jié)果如下:
第二個(gè)窗口記得提交commit;。
三、加鎖演示(for update nowait)
1、打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi' for update nowait;
輸出結(jié)果:
2、再打開一個(gè)postgreSQL的SQL Shell或pgAdmin的SQL編輯器窗口,執(zhí)行:
begin;
select * from db_user where name='lisi' for update nowait;
輸出結(jié)果:
不會(huì)進(jìn)行資源等待,返回錯(cuò)誤信息。
3、第一個(gè)窗口執(zhí)行:
commit;
提交成功,資源鎖釋放。
總結(jié):
for update nowait和 for update 都會(huì)對(duì)所查詢到得結(jié)果集進(jìn)行加鎖,所不同的是,如果另外一個(gè)線程正在修改結(jié)果集中的數(shù)據(jù),for update nowait 不會(huì)進(jìn)行資源等待,只要發(fā)現(xiàn)結(jié)果集中有些數(shù)據(jù)被加鎖,立刻返回 “55P03錯(cuò)誤,內(nèi)容是無(wú)法在記錄上獲得鎖.
命令說(shuō)明:
begin;--開啟事務(wù)
begin transaction;--開啟事務(wù)
commit;--提交
rollback;--回滾
set lock_timeout=5000;--設(shè)置超時(shí)時(shí)間
注意:
連表查詢加鎖時(shí),不支持單邊連接形式,例如:
select u.*,r.* from db_user u left join db_role r on u.roleid=r.id for update;
支持以下形式,并鎖住了兩個(gè)表中關(guān)聯(lián)的數(shù)據(jù):
select u.*,r.* from db_user u, db_role r where u.roleid=r.id for update;
補(bǔ)充:PostgreSQL select for update指定列(兼容oracle)
我們可以使用select for update語(yǔ)句來(lái)指定鎖住某一張表,在oracle中我們可以在for update語(yǔ)句后指定某一列,用來(lái)單獨(dú)鎖定指定列的數(shù)據(jù)。
oracle例子:
建表:
SQL> create table t1(id int, c2 varchar(20), c3 int, c4 float, c5 float);
Table created.
SQL> create table t2(id int, c6 int);
Table created.
SQL> insert into t1 values (1, 'SA_REP', 1, 100, 1);
1 row created.
SQL> insert into t1 values (1, 'SA_REP123', 1, 100, 1);
1 row created.
SQL> insert into t2 values (1, 2500);
1 row created.
查詢:
我們使用下列查詢用來(lái)只鎖住c4列。
SQL> SELECT e.c3, e.c4, e.c5
2 FROM t1 e JOIN t2 d
USING (id)
WHERE c2 = 'SA_REP'
AND c6 = 2500
3 4 5 6 FOR UPDATE OF e.c4
7 ORDER BY e.c3;
C3 C4 C5
---------- ---------- ----------
1 100 1
PostgreSQL兼容方法:
建表:
create table t1(id int, c2 text, c3 int, c4 float, c5 float);
create table t2(id int, c6 int);
insert into t1 values (1, 'SA_REP', 1, 100, 1);
insert into t1 values (1, 'SA_REP123', 1, 100, 1);
insert into t2 values (1, 2500);
pg中使用方法和oracle類似,只是需要將order by語(yǔ)法放到前面,并且將列名換成表名。
bill=# SELECT e.c3, e.c4, e.c5
bill-# FROM t1 e JOIN t2 d
bill-# USING (id)
bill-# WHERE c2 = 'SA_REP'
bill-# AND c6 = 2500
bill-# ORDER BY e.c3
bill-# FOR UPDATE OF e ;
c3 | c4 | c5
----+-----+----
1 | 100 | 1
(1 row)
驗(yàn)證:
我們可以驗(yàn)證下pg中是否只鎖定了指定的行。
1、安裝pgrowlocks插件
bill=# create extension pgrowlocks;
CREATE EXTENSION
2、觀察
t1表被鎖:
bill=# select * from pgrowlocks('t1');
locked_row | locker | multi | xids | modes | pids
------------+--------+-------+--------+----------------+--------
(0,1) | 1037 | f | {1037} | {"For Update"} | {2022}
(1 row)
t2表沒(méi)有被鎖:
bill=# select * from pgrowlocks('t2');
locked_row | locker | multi | xids | modes | pids
------------+--------+-------+------+-------+------
(0 rows)
我們還可以再看看t1表中具體被鎖住的數(shù)據(jù):
bill=# SELECT * FROM t1 AS a, pgrowlocks('t1') AS p
bill-# WHERE p.locked_row = a.ctid;
id | c2 | c3 | c4 | c5 | locked_row | locker | multi | xids | modes | pids
----+--------+----+-----+----+------------+--------+-------+--------+----------------+--------
1 | SA_REP | 1 | 100 | 1 | (0,1) | 1037 | f | {1037} | {"For Update"} | {2022}
(1 row)
除此之外,pg中for update子句還有其它的選項(xiàng):
UPDATE – 當(dāng)前事務(wù)可以改所有字段
NO KEY UPDATE – 當(dāng)前事務(wù)可以改除referenced KEY以外的字段
SHARE – 其他事務(wù)不能改所有字段
KEY SHARE – 其他事務(wù)不能改referenced KEY字段
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
您可能感興趣的文章:- PostgreSQL 實(shí)現(xiàn)登錄及修改密碼操作
- postgresql表死鎖問(wèn)題的排查方式
- Postgresql - 查看鎖表信息的實(shí)現(xiàn)
- 基于postgresql數(shù)據(jù)庫(kù)鎖表問(wèn)題的解決
- Postgresql鎖機(jī)制詳解(表鎖和行鎖)
- postgresql查詢鎖表以及解除鎖表操作
- PostgreSQL中關(guān)閉死鎖進(jìn)程的方法
- PostgreSQL用戶登錄失敗自動(dòng)鎖定的處理方案