GaussDB(DWS) 锁管理介绍
一,表锁
GaussDB(DWS) 支持的表锁级别很多,从最低的1级到最高的8级:
1级锁,AccessShareLock
SELECT语句申请AccessShareLock,只与8级锁冲突,只会阻塞DDL等语句。
2级锁,RowShareLock
SELECT FOR SHARE/UPDATE语句申请RowShareLock,与7/8级锁冲突。
3级锁,RowExclusiveLock
INSERT/UPDATE/DELET语句申请RowExclusiveLock,与6-8级锁冲突。
4级锁,ShareUpdateExclusiveLock
VACUUM/ANALYZE语句申请ShareUpdateExclusiveLock,与5-8级锁冲突。
5级锁,ShareLock
CREATE INDEX语句申请ShareLock,与4/6/7/8级锁冲突,与5级锁不冲突,同一个表的多个CREATE INDEX可以同时执行不阻塞。
6级锁,ShareRowExclusiveLock
在GaussDB(DWS) 中,ShareRowExclusiveLock目前只在ALTER SEQUENCE中用到,阻塞表的增删改以及更高级别操作,该锁与3-8级锁冲突。
7级锁,ExclusiveLock
VACUUM FULL,MERGE PARTITION等语句申请ExclusiveLock级锁,ExclusiveLock只与SELECT兼容,与2-8级锁冲突。
除了表锁外,事务锁,扩展锁、记录锁都是使用的ExclusiveLock,下面会进行详细介绍。
8级锁,AccessExclusiveLock
DDL等语句会申请AccessExclusiveLock,包括ALTER TABLE,DROP TABLE,TRUNCATE,REINDEX,VACUUM FULL等,8级锁与所有锁都冲突。
锁冲突矩阵
详细的锁冲突矩阵图如下所示:
LOCK [TABLE]
表锁还可以手动的使用SQL语句的方式进行强制上锁,SQL语句的格式如下所示:
LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
其中 lockmode 可以是以下之一:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
要注意的是LOCK语句只能在事务块中执行,事务结束会释放。
二,其他锁
除了表锁,GaussDB(DWS) 中还有很多其他的锁,下面列出一些常用的锁:
1,事务锁
写事务会获取一个事务号,并且会以这个事务号申请一个事务锁,锁级别是7级锁ExclusiveLock。
事务锁用于控制记录的并发修改,比如,两个事务先后修改同一条记录,在前一个事务未结束之前,后一个事务会等待在前一个事务的事务锁上。
2,记录锁
当出现并发更新冲突时,冲突的事务会申请记录锁,锁级别是7级锁ExclusiveLock。
记录锁主要是提高等待事务的优先级,在更新事务结束后,让持有记录锁的事务第一个被唤醒。
3,扩展锁
文件扩展时,会申请扩展锁,扩展锁的锁级别是7级锁ExclusiveLock。
表、索引、fsm、vm等文件扩展时都会申请扩展锁。
4,分区锁
分区锁是专门针对分区表的,分区锁的意义与表锁差不多,锁级别从1-8都有。
三,用户自定义锁
也叫advisory lock,用户可以通过调用GaussDB(DWS) 提供的函数来自定义锁,自定义锁按照作用范围分为两类:
1,事务级自定义锁
作用范围在本事务内部,可以手动调用函数释放,也可以事务结束自动释放。相关函数:
pg_advisory_xact_lock(key bigint)
pg_advisory_xact_lock(key1 int, key2 int)
pg_advisory_xact_lock_shared(key bigint)
pg_advisory_xact_lock_shared(key1 int, key2 int)
pg_try_advisory_xact_lock(key bigint)
pg_try_advisory_xact_lock(key1 int, key2 int)
pg_try_advisory_xact_lock_shared(key bigint)
pg_try_advisory_xact_lock_shared(key1 int, key2 int)
2,session级自定义锁
作用范围跨越事务,需要手动调用相关函数进行合理的释放,session退出时也会强制释放。相关函数:
pg_advisory_lock(key bigint)
pg_advisory_lock(key1 int, key2 int)
pg_advisory_lock_shared(key bigint)
pg_advisory_lock_shared(key1 int, key2 int)
pg_try_advisory_lock(key bigint)
pg_try_advisory_lock(key1 int, key2 int)
pg_try_advisory_lock_shared(key bigint)
pg_try_advisory_lock_shared(key1 int, key2 int)
其中:
带shared后缀的相关函数会申请5级锁ShareLock,不带shared后缀的会申请7级锁ExclusiveLock。
带try标识的相关函数表示尝试申请锁,如果申请不到,直接返回,不需锁等待
四,如何查看锁等待
通过查询pg_locks视图查看单个节点的锁持有和等待状态,pg_locks视图的结构如下图:
其中:
locktype列表示锁类型,包括表锁、事务锁、扩展锁、自定义锁等;
relation列表示表的oid,如果是表锁,relation列会显示表的oid
transactionid表示事务号,如果是事务锁,transactionid列会显示session的事务号
mode列表示锁级别,级别1-8级;
pid列表示session的线程号;
granted列表示是否持有锁,‘t’表示持有锁,‘f'表示等待锁;
简单示例
先创建一张表t1(a int, b int);
并插入一条记录(1,1)。
1,先后创建两个连接session1,session2,同时对这条记录进行更新,更新顺序如下:
2,对于session1,查看pg_locks,如下图所示
session1持有的锁主要包括:
1)持有表t1的3级锁RowExclusiveLock,表t1的oid是16384
2)持有session1的事务锁,事务号是2415620,锁级别7级(ExclusiveLock)
3,对于session2,查看pg_locks,如下图所示
由于session1的更新未结束,session2需要等待,session2相关的锁主要包括:
1)持有表t1的3级锁RowExclusiveLock,表t1的oid是16384
2)持有session2的事务锁,事务号是2415630
3)持有记录(1,1)的记录锁
4)等待session1事务结束释放事务锁,granted为’f',申请session1的事务号对应的5级锁(ShareLock),与session1持有7级事务锁冲突,需要锁等待
五,锁相关参数
GaussDB(DWS) 中锁等待可以设置等待超时相关参数,一旦等锁的时间超过参数配置值会抛错。
锁等待超时有两个参数::
1) lockwait_timeout
当出现表锁冲突的时候生效,当等待表锁的时间超过配置的时间,抛错返回,默认20分钟。
2) update_lockwait_timeout
当出现记录锁冲突的时候生效,如果等待记录锁的时间超过update_lockwait_timeout,抛错返回,默认20分钟。
- 点赞
- 收藏
- 关注作者
评论(0)