首页 > 数据库 > PostgreSQL > PostgreSQL:锁
脏读:一个事务可以读到另一个事务中未提交的数据
不可重复读:在一个事务没有结束时,另外一个事务也访问该同一数据集合,并做了 DML 操作。因此,在第一个事务两次读数据之间,读到的数据可能是不一样的
幻读(丢失更新):一个事务的更新操作会被另一个事务的更新操作所覆盖,从而导致数据的不一致。
READ UNCOMMITTED
允许事务查看其他事务所进行的未提交更改
允许“脏”读、 不可重复读和虚读。
READ COMMITTED
允许事务查看其他事务所进行的已提交更改
不允许“脏”读。 但允许不可重复读和虚读。
只支持二进制格式为 ROW 情况下
REPEATABLE READ
确保每个事务的 SELECT 输出一致
SERIALIZABLE
将一个事务的结果与其他事务完全隔离, 即一个事务所选的行不能由其他事务更改, 直到该事务完成为止。
分布式事务常用。
表级锁模式
锁模式 | 描述 |
---|---|
ACCESS SHARE | SELECT 命令将在所引用的表上加此类型的锁。通常只读取表而不修改表的查询都会请求这种锁模式 |
ROW SHARE | SELECT FOR UPDATE 和 SELECT FOR SHARE 命令会在目标表上加此类型的锁 |
ROW EXCLUSIVE | UPDATE、DELETE、INSERT 命令会自动在所修改的表上请求加这个锁。通常,修改表中数据的命令都是加这种锁 |
SHARE UPDATE EXCLUSIVE | 这个模式保护一个表,在模式改变和运行 VACUUM 并发、ANALYZE/CREATE INDEX CONCURR-ENTLY 命令请求这样的锁 |
SHARE | 这个模式可避免表的并发数据修改。CREATE INDEX (不带 CONCURRENTLY 选项)语句要求这样的锁模式 |
SHARE ROW EXCLUSIVE | 任何 PostgreSQL 命令都不会自动请求这个锁模式 |
EXCLUSIVE | 这个模式只允许并发 ACCESS SHARE 锁,也就是说,只有对表的度动作可以和持有这个锁的事务并发执行。任何 PostgreSQL 命令都不会用户表上自动请求这个锁模式。不过,在执行某些操作时,会在某些系统上请求这个锁。 |
ACCESS EXCLUSIVE | 这个模式只能保证只有一个人访问此表。ALTER TABLE、DROP TABLE、TRUNCATE、REINDEX、CLUSTER、VACUUM FULL 命令要求这样的锁。在 LOCK TABLE 命令中没有明确声明需要的锁模式时,它是默认锁模式 |
行级锁模式:只有两种,即“共享锁”和“排他锁”,或者可以说是“读锁”或“写锁”。而在 PostgreSQL 中不称其为“读锁”的原因是,由于有多版本的实现,所以实际读取数据时,并不会在行上执行任何锁。
LOCK [ TABLE ] [ ONLY ] name [, ...] [ IN lockmode MODE ] [ NOWAIT ]
name:表名
lockmode:八种锁模式
NOWAIT:如果没有 NOWAIT 这个关键字时,当无法获得锁时,会一直等待,而如果加了 NOWAIT 关键字,在无法立即获取该锁时,此命令会立即退出并且发出一个错误信息。
SELECT ...... FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...]
[ OF table_name [, ...] ]:如果明确了表名字,那么只有这些被指定的表会被锁定,其他在 SELECT 中使用的表将不会被锁定。
若主查询中引用了 WITH 查询时,WITH 查询中的表并不会被锁定。如果想锁定 WITH 查询内的表行,需要在 WITH 查询内指定 FOR UPDATE 或 FOR SHARE 关键字。
列名称 | 列类型 | 引用 | 描述 |
---|---|---|---|
locktype | text | 被锁定的对象类型 | |
database | oid | pg_database.oid | 锁定对象之数据库的 OID,如果对象是一个共享对象,不属于任何一个数据库,此值为 0,如果对象是“transaction ID”,此值为空 |
relation | oid | pg_class.oid | 如果对象不是表或只是表的一部分,则此值为 null,否则此值是表的 OID |
page | integer | 表中的页号,如果对象不是表行 (tuple) 或表页 (relation page),则此值为 null | |
tuple | smallint | 页内的行号 (tuple),如果对象不是表行 (tuple),则此值为空 | |
virtualxid | text | 是一个虚拟事务 ID (ID of a transaction),如果对象不是虚拟事务,则此值为 null | |
transactionid | xid | 事务 ID (ID of a transaction),如果对象不是事务 ID,此值则为 null | |
classid | oid | pg_class.oid | 包含该对象的系统目录 (system catalog) 的 OID,如果对象不是通常的数据库对象,则此值为空 |
objid | oid | any OID column | 对象在系统目录(system catalog) 中的 OID,如果对象不是通常的数据库对象,则此值为空。对于 advisory locks,此字段用于区别两类 key 空间(1 表示 int8 的 key,2 表示 two int4 的 key) |
objsubid | smallint | 如果对象是表列 (table column),此列的值为列号,这时“classid”和“objid”指向表,在其他的数据库类型中,此值为 0;如果不是数据库对象,则此值为 null | |
virtualtransaction | text | 持有或等待这把锁的虚拟事务的 ID (Virtual ID of the transaction) | |
pid | integer | 持有或等待这把锁的服务进程的 pid。如果此锁是被一个两阶段的事务持有,则此值为 null | |
mode | text | 锁的模式名称 | |
granted | boolean | 如果锁已被持有,此之为“True”;如果等待获得此锁,则此值为“False” |
事务 ID 字段详解
transactionid-->xid:普通事务 ID
virtualxid-->vxid:只读事务 ID
virtualtransaction:表示持有锁或等待锁 session 的虚拟事务 ID。
SELECT locktype, relation::regclass as rel, page||','||tuple as ctid, virtualxid as vxid, transactionid as xid, virtualtransaction as vxid2, pid, mode, granted FROM pg_locks;
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31490526/viewspace-2742209/,如需转载,请注明出处,否则将追究法律责任。