测试PostgreSQL行级锁

1.打开三个psql窗口,连接到postgreSQL数据库

  查看窗口连接到的服务进程的pid。

select pg_backend_pid();

         

2.在第一个窗口更新一行数据

mydb=# begin;
BEGIN
mydb=# select * from student  where id =1 for update;
+----+-------+
| id | name  |
+----+-------+
|  1 | April |
+----+-------+
(1 行记录)

3.在第三个窗口查看数据库中锁的情况

select locktype,relation::regclass, virtualxid, transactionid, virtualtransaction ,pid, mode, granted from pg_locks where pid = 28924;

    由上图可知:加行锁的过程,不仅会先在表上加表级意向锁,也会在相应的主键上加意向锁。

    图中没有显示行锁信息,原因是行锁信息不会记录到共享内存中。如果每个行锁都在内存有一条记录的话,全表更新时,表有多少行,就在内存中有多少条行锁信息,那么内存会吃不消。因此,PostgreSQL在内存中并不记录行锁的信息。

    没有行锁的信息,如何知道一个进程被另一个进程的行锁给阻塞了呢?看下面演示。

4.在第二个窗口也对更新一行数据

mydb=# begin;
BEGIN
mydb=# select * from student  where id =1 for update;

5.在第三个窗口查看数据库中锁的情况

select locktype,relation::regclass, virtualxid, transactionid, virtualtransaction ,pid, mode, granted from pg_locks where pid in (28924,2052);

    倒数第三行,2052进程(第二个psql窗口对应的数据库服务进程)申请锁时被阻塞了,这个锁的transactionid为17482328。

    倒数第二行,transactionid为17482328的锁,被进程28924持有(第一个psql窗口对应的数据库服务进程)。

    行锁的阻塞信息通过“transactionid”类型的锁体现出来。从原理上讲,行锁会在数据行上加上自己的transactionid。另一个进程读到这一行时,如果发现有行锁,会transactionid读出来,然后申请在这个transactionid上加“share”锁。而持有行锁的进程已经在此transactionid上加了“Exclusive”锁,因此后面的进程会被阻塞。

猜你喜欢

转载自blog.csdn.net/liyazhen2011/article/details/83379225