在博文《数据库并发事务控制四:postgresql数据库的锁机制 》
http://blog.csdn.net/beiigang/article/details/43302947
中后面提到:

常规锁机制可以参考pg的官方手册,章节和内容见下面
13.3. Explicit Locking
http://www.postgresql.org/docs/9.4/static/explicit-locking.html
这节分为:表锁、行锁、页锁、死锁、Advisory锁(这个名字怎么翻译好??? 忠告锁,公告锁,咨询锁???)。

后面的内容提纲就是:
表锁、
行锁、
页锁、
死锁、
Advisory锁(这个名字怎么翻译好??? 忠告锁,公告锁,咨询锁???)、
查看锁。

感觉有些累了,懒了,不想写了,后面看情况到网上找些同仁同志同学朋友们的文章,放到这儿归类,如有需要待下次按我的思路再整理组织,今次先把题目做完整吧。

这儿继续,下面的内容转自下面,只是小改了几处手误的地方,把第三节的图换成了官网上的

http://francs3.blog.163.com/blog/static/40576727201082134343604/

原文标题:Postgresql 锁浅析

一、概述
此文档主要对Postgresql 锁机制进行分析,在讲解的过程中结合实验,理解Postgresql的锁机制。

二、表级锁类型
表级锁类型分为八种,以下对各种表级锁类型进行简单介绍下, 锁的冲突模式可以参考3.1的图一:表级锁冲突模式。

2.1 ACCESS SHARE
“ACCESS SHARE”锁模式只与“ACCESS EXCLUSIVE” 锁模式冲突;
查询命令(Select command)将会在它查询的表上获取”Access Shared” 锁,一般地,任何一个对表上的只读查询操作都将获取这种类型的锁。

2.2 ROW SHARE
 “Row Share” 锁模式与”Exclusive’和”Access Exclusive”锁模式冲突;
”Select for update”和”Select for share”命令将获得这种类型锁,并且所有被引用但没有 FOR UPDATE 的表上会加上”Access shared locks”锁。

2.3 ROW EXCLUSIVE
 “Row exclusive” 与 “Share,Shared roexclusive,Exclusive,Access exclusive”模式冲突;
“Update,Delete,Insert”命令会在目标表上获得这种类型的锁,并且在其它被引用的表上加上”Access shared”锁,一般地,更改表数据的命令都将在这张表上获得”Row exclusive”锁。

2.4 SHARE UPDATE EXCLUSIVE
”Share update exclusive,Share,Share row ,exclusive,exclusive,Access exclusive”模式冲突,这种模式保护一张表不被并发的模式更改和VACUUM;
 “Vacuum(without full), Analyze ”和 “Create index concurrently”命令会获得这种类型锁。

2.5 SHARE
与“Row exclusive,Shared update exclusive,Share row exclusive ,Exclusive,Access exclusive”锁模式冲突,这种模式保护一张表数据不被并发的更改;
“Create index”命令会获得这种锁模式。

2.6 SHARE ROW EXCLUSIVE
与“Row exclusive,Share update exclusive,Shared,Shared row exclusive,Exclusive,Access Exclusive”锁模式冲突;
任何Postgresql 命令不会自动获得这种锁。

2.7 EXCLUSIVE
与” ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE, SHARE, SHARE ROW
EXCLUSIVE, EXCLUSIVE, ACCESS EXCLUSIVE”模式冲突,这种索模式仅能与Access Share
模式并发,换句话说,只有读操作可以和持有”EXCLUSIVE”锁的事务并行;
任何Postgresql 命令不会自动获得这种类型的锁;

2.8 ACCESS EXCLUSIVE
与所有模式锁冲突(ACCESS SHARE, ROW SHARE, ROW EXCLUSIVE, SHARE UPDATE EXCLUSIVE,
SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE, and ACCESS
EXCLUSIVE),这种模式保证了当前只有一个事务访问这张表;
“ALTER TABLE, DROP TABLE, TRUNCATE, REINDEX, CLUSTER, VACUUM FULL” 命令会获得这种类型锁,在Lock table 命令中,如果没有申明其它模式,它也是缺省模式。

三、表级锁冲突模式
3.1  Conflicting lock modes

Table 13-2. Conflicting Lock Modes

Requested Lock Mode Current Lock Mode
ACCESS SHARE ROW SHARE ROW EXCLUSIVE SHARE UPDATE EXCLUSIVE SHARE SHARE ROW EXCLUSIVE EXCLUSIVE ACCESS EXCLUSIVE
ACCESS SHARE X
ROW SHARE X X
ROW EXCLUSIVE X X X X
SHARE UPDATE EXCLUSIVE X X X X X
SHARE X X X X X
SHARE ROW EXCLUSIVE X X X X X X
EXCLUSIVE X X X X X X X
ACCESS EXCLUSIVE X X X X X X X X

备注: 上图是pg 表级锁的各种冲突模式对照表,‘X’表示冲突项, 在章节四中会对其中典型的锁模式进行模似演示。

四、实验
在这一章节中将会对图一中比较典型的锁冲突进行模似演练,了解这些在Postgresql DBA的日常维护工作中很有帮助,同时也能减少人为故障的发生。

4.1  Access exclusive 锁与Access share锁冲突
       在日常维护中,大家应该执行过’ALTER
TABLE’更改表结构的DDL,例如加字段,更改字段数据类型等,根据章节二的理论,在执行’ALTER TABLE’命令时将申请一个Access
exclusive锁, 根据图一,大家知道Access exclusive
锁和所有的锁模式都冲突,那么,它将会’Select’命令冲突,因为Select 加的是Access
share锁,那么真的会与‘SELECT‘命令冲突吗,接下来给大家演示下:

--创建一张测试表 test_2 并插入测试数据
mydb=> create table test_2 (id integer,name varchar(32));
CREATE TABLE
mydb=> insert into test_2 values (1,'franc');
INSERT 0 1
mydb=> insert into test_2 values (2,'tan');
INSERT 0 1
mydb=> select * from test_2;
 id | name
----+-------
  1 | franc
  2 | tan
(2 rows)

--会话一 查询表数据 ( 这里获得Access Shared 锁)
mydb=> begin;
BEGIN
mydb=> select * from test_2 where id=1;
 id | name
----+-------
  1 | franc
(1 row)
注意:这里begin开始事务,没有提交;

--会话二 更改表结构 (这里申请 Access Exclusive锁 )
mydb=> alter table test_2 add column sex char(1);
发现,命令一直等侍,执行不下去;

--会话三 查询状态
mydb=# select oid,relname from pg_class where relname='test_2';
  oid  | relname
-------+---------
 33802 | test_2
mydb=# select locktype,database,relation,pid,mode from pg_locks where relation='33802';
 locktype | database | relation |  pid  |        mode        
----------+----------+----------+-------+---------------------
 relation |    16466 |    33802 | 18577 | AccessShareLock
 relation |    16466 |    33802 | 18654 | AccessExclusiveLock
mydb=# select datname,procpid,usename,current_query from pg_stat_activity where procpid in (18577,18654);
 datname | procpid | usename |               current_query               
---------+---------+---------+--------------------------------------------
 mydb    |   18577 | skytf   | <IDLE> in transaction
 mydb    |   18654 | skytf   | alter table test_2 add column sex char(1);
(2 rows)
     这里可以看出会话一(pid=18577) 获取的是 “AccessShareLock”锁,
会话二(pid=18654 ) 获取的是 “AccessExclusiveLock”锁。

--再次回到会话一,执行'end'结束事务后会发生什么结果
注意,此时会话二还处于等侍状态
mydb=> end;
COMMIT

--回到会话二发现 原来处于等侍状态的'ALTER TABLE'命令执行成功
mydb=> alter table test_2 add column sex char(1);
ALTER TABLE
mydb=> \d test_2
            Table "skytf.test_2"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 id     | integer               |
 name   | character varying(32) |
 sex    | character(1)          |

--回到会话三,锁已经释放
mydb=# select locktype,database,relation,pid,mode from pg_locks where relation='33802';
 locktype | database | relation | pid | mode
----------+----------+----------+-----+------
(0 rows)
mydb=# select datname,procpid,usename,client_addr,current_query from pg_stat_activity where procpid in (18577,18654);
 datname | procpid | usename | client_addr | current_query
---------+---------+---------+-------------+---------------
 mydb    |   18577 | skytf   |             | <IDLE>
 mydb    |   18654 | skytf   |             | <IDLE>
(2 rows)
实验说明: 这个实验说明了 'ALTER TABLE'命令与'SELECT'命令会产生冲突,证实了开始的结论,即"Access exclusive"锁模式与申请"Access shared"锁模式的'SELECT'命令相冲突。

4.2  Share 锁与 Row Exclusive 锁冲突
在数据库的维护过程中,创建索引也是经常做的工作,别小看创建索引,如果是一个很繁忙的系统,索引不一定能创建得上,可能会发生等侍, 严重时造成系统故障;根据章节二的理论,’Create Index’ 命令需要获取Share 锁模式。
根据图一,”Share” 锁和”Row Exclusive”锁冲突,下面来验证一下:
根据图一可以看出,share锁模式和多种锁模式冲突,有可能会问我,为什么单独讲share锁和Row Exclusive冲突呢?因为”
Update,Delete,Insert”命令获取的是Row Exclusive
操作,而这种操作在生产过程中非常频繁;这个实验正是模似生产维护过程。
 
--会话一, 向 test_2 上插入一条数据
mydb=> select * from test_2;
 id | name  | sex
----+-------+-----
  1 | franc |
  2 | tan   |
(2 rows)
mydb=> begin;
BEGIN
mydb=> insert into test_2 values (3,'fpzhou');
INSERT 0 1
mydb=>
说明: 这个Insert 操作放在一个事务里,注意此时事务尚未提交。

--会话二,在表test_2上创建索引
mydb=> \d test_2;
            Table "skytf.test_2"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 id     | integer               |
 name   | character varying(32) |
 sex    | character(1)          |
mydb=> create unique index idx_test_2_id  on test_2 (id);
说明: 创建索引命令发生等侍

--会话三,查询状态
mydb=# select locktype,database,relation,pid,mode from pg_locks where relation='33802';
 locktype | database | relation |  pid  |       mode      
----------+----------+----------+-------+------------------
 relation |    16466 |    33802 | 18577 | RowExclusiveLock
 relation |    16466 |    33802 | 18654 | ShareLock
(2 rows)
mydb=# select datname,procpid,usename,client_addr,current_query from pg_stat_activity where procpid in (18577,18654);
 datname | procpid | usename | client_addr |                   current_query                   
---------+---------+---------+-------------+----------------------------------------------------
 mydb    |   18577 | skytf   |             | <IDLE> in transaction
 mydb    |   18654 | skytf   |             | create unique index idx_test_2_id  on test_2 (id);
 说明:  这里可以看出"Insert into"(procpid=18577) 命令获取"RowExclusiveLock”,而"Create
Index"(procpid=18654)操作获取的是"Sharelock", 并且创建索引操作发了等侍,因为这两种锁模式是冲突的。

--回到会话一,提交事务,看看会发生什么
注意,此时创建索引的会话二仍处于等侍状态
mydb=> end;
COMMIT

--回到会话二,发现创建索引命令成功,等侍消失
mydb=> create unique index idx_test_2_id  on test_2 (id);
CREATE INDEX
实验结论:1 上述实验说明 "Create index "操作和"Insert"操作冲突;也就是 "Share"锁和"RowExclusive"锁冲突。
          2 在生产库上应该避免在业务高峰期执行新建索引操作,因为如果在张大表上新建索引,消耗时间较长,在这个过程中会阻塞业务的DML操作。

4.3  SHARE UPDATE EXCLUSIVE 与自身冲突
       根据章节二,大家知道 VACUUM(Without full), Analyze 和 Create index
(Concurently)操作会申请获得”Shared update Exclusive 锁”。根据图一,”Shared update
Exclusive 锁”与本身也是会冲突的,下面实验验证一下:

--会话一,分析表test_2

mydb=> select * from test_2;
 id |  name  | sex
----+--------+-----
  1 | franc  |
  2 | tan    |
  3 | fpzhou |
(3 rows)
mydb=>
mydb=>
mydb=> begin;
BEGIN
mydb=> analyze test_2;
ANALYZE      
注意: 表分析放在一个事务里,此时并没有提交;

--会话二 对表 test_2 做 vacuum
mydb=> \d test_2;
            Table "skytf.test_2"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 id     | integer               |
 name   | character varying(32) |
 sex    | character(1)          |
Indexes:
    "idx_test_2_id" UNIQUE, btree (id)
mydb=> vacuum test_2;
注意: 当对表 test_2 执行 vacuum操作时,操作等侍,

--会话三,观察系统哪里锁住了
[postgres@pg1 ~]$ psql -d mydb
psql (9.0beta3)
Type "help" for help.
mydb=# select datname,procpid,waiting,current_query from pg_stat_activity where waiting='t';
 datname | procpid | waiting | current_query
---------+---------+---------+----------------
 mydb    |   20625 | t       | vacuum test_2;
(1 row)
这里说明会话 vacuum test_2 在等侍

mydb=# select oid,relname from pg_class where relname='test_2';
  oid  | relname
-------+---------
 33802 | test_2
(1 row)
mydb=# select locktype,database,relation,pid,mode from pg_locks where relation='33802';
 locktype | database | relation |  pid  |           mode          
----------+----------+----------+-------+--------------------------
 relation |    16466 |    33802 | 20625 | ShareUpdateExclusiveLock
 relation |    16466 |    33802 | 20553 | ShareUpdateExclusiveLock
 (2 rows)
 说明: 这里可以看出 'Analyze'操作 (pid=20553) 和'Vacuum'操作 (pid=20625)都是加的"ShareUpdateExclusiveLock"。

mydb=# select datname,procpid,waiting,current_query from pg_stat_activity where procpid in (20625,20553);
 datname | procpid | waiting |     current_query    
---------+---------+---------+-----------------------
 mydb    |   20553 | f       | <IDLE> in transaction
 mydb    |   20625 | t       | vacuum test_2;
(2 rows)
说明: 结束上面查询可以看出会话20625在等侍会话20553,也就是说"vacuum test_2" 被事务堵住了,

--再次回到会话一,提交会话,注意此时会话二处于等侍姿态;
mydb=> end;
COMMIT

--再次回到会话二,发现 vacuum命令执行下去了,等侍消失。
mydb=> vacuum test_2;
VACUUM
mydb=>  select datname,procpid,waiting,current_query from pg_stat_activity where waiting='t';
 datname | procpid | waiting | current_query
---------+---------+---------+---------------
(0 rows)
实验结论 1 Analyze 和 Vacuum 操作都会申请获得 "ShareUpdateExclusiveLock"。
         2 ShareUpdateExclusiveLoc与ShareUpdateExclusiveLock是冲突的。

转自 http://blog.csdn.net/beiigang/article/details/43339327

数据库并发事务控制四:postgresql数据库的锁机制二:表锁 <转>的更多相关文章

  1. 数据库事务 ACID属性、数据库并发问题和四种隔离级别

    数据库事务 ACID属性.数据库并发问题和四种隔离级别 数据库事务 数据库事务是一组逻辑操作单元,使数据从一种状态变换到另一种状态 一组逻辑操作单元:一个或多个DML操作 事务处理原则 保证所有事务都 ...

  2. 代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性

    做人事档案的系统考虑到数据的安全性与一致性,毕竟是要对外上线.真正投入使用的项目,数据库的可靠性与安全性上我们开发人员要考虑的就很多了,记得做机房收费系统时注册新卡是自己为了简单,写成了一个存储过程( ...

  3. 数据库并发及锁机制及Hibernate锁实现

    数据库事务的定义 数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作.一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性.一致性.隔离性和持久性) ...

  4. mysql锁机制之行锁(四)

    前言 顾名思义,行锁就是一锁锁一行或者多行记录,mysql的行锁是基于索引加载的,所以行锁是要加在索引响应的行上,即命中索引,如下图所示: InnoDB 支持多粒度锁(multiple granula ...

  5. 【连载】redis库存操作,分布式锁的四种实现方式[四]--基于Redis lua脚本机制实现分布式锁

    一.redis lua介绍 Redis 提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题.Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向 ...

  6. MYSQL数据库重点:事务与锁机制

    一.事务 一组连续的数据库操作,每一次操作都成功,整个事务就成功,只要有一步出错,整个事务就失败: MySQL事务与存储引擎相关 1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB: ...

  7. C# 数据库并发的解决方案(通用版、EF版)

    自ASP.NET诞生以来,微软提供了不少控制并发的方法,在了解这些控制并发的方法前,我们先来简单介绍下并发! 并发:同一时间或者同一时刻多个访问者同时访问某一更新操作时,会产生并发! 针对并发的处理, ...

  8. mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理

    一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...

  9. 简单理解:数据库的一致性与四种隔离级别(+MySQL实现)

    并行数据库存在着几种常见不一致问题: 1.更新丢失:两个并发的写进程同时修改某内容,一个没修改完提交之后另一个又提交,导致其覆盖了第一个提交的写进程内容. 2.脏读:一个操作读到了另外一个操作没有提交 ...

随机推荐

  1. mysql 5.5数据库主从配置步骤详解

    上次给大家介绍了mysql 5.1主从搭建配置教程,这次我们来实现mysql 5.5的主从复制,其实大体上配置是差不多的,只有点细微的差别. 系统:centos 5.x 需要的软件包:mysql-5. ...

  2. [转]21分钟 MySQL 入门教程

    目录 一.MySQL的相关概念介绍 二.Windows下MySQL的配置 配置步骤 MySQL服务的启动.停止与卸载 三.MySQL脚本的基本组成 四.MySQL中的数据类型 五.使用MySQL数据库 ...

  3. 另辟蹊径 直取通州的“墨迹天气”APP应用的成功故事

    一个天气应用,曾被认为是要挑战国家气象局,网站也莫名其妙地被封,两个合伙人先后离开.创始人金犁是如何把这么一款工具类应用做到人所共知的? 采访 | 郑江波 翟文婷 文 | 翟文婷 出生时间:1982年 ...

  4. vivado烧写bin文件到flash 中

    点击 bitstream setting ,将 bin_file 勾上,点击 OK. 2)点击 generate bitstream ,生成 bit 文件和 bin 文件 3)点击 open hard ...

  5. 用casperjs模拟登录,支持多个账户登录

    var casper = require('casper').create({ viewportSize:{ width:1920, height:1080 } }); var url1 = 'htt ...

  6. RequestDispatcher.forward和HttpServletResponse.sendRedirect

    (1)RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件:而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程 ...

  7. EF框架 对字段属性为NULL的空值处理 类型前面加上?保证EF列表读取显示数据不会报异常

    譬如: public int? FlowStatus { get; set; } public DateTime? UpdateTime { get; set; }

  8. Linux/CentOS关闭图形界面(X-window)和启用图形界面命令

    1.在图像界面关闭x window:1.1 shell中运行 init 3  进入文本模式,同时会关闭相关的服务(Xserver 肯定关闭)1.2 Alt+Ctrl+F1~F6到字符界面,root登陆 ...

  9. 安全管理中心(SOC)引导企业信息安全建设的思路

    SOC即企业安全管理中心,该模型可帮助企业信息安全人员在进行安全建设方面提供整体性的参考.如下所示,以下模型分为数据采集部分收集了各类设备及日志等数据,这些数据收集到了以后提供给SOC安全管理中心,而 ...

  10. vim学习笔记(10):vim命令大全

    进入vim的命令: vim filename :打开或新建文件,并将光标置于第一行首 vim +n filename :打开文件,并将光标置于第n行首 vim + filename :打开文件,并将光 ...