GaussDB(DWS) 锁管理介绍

举报
飞翔的罗杰 发表于 2020/12/23 17:42:14 2020/12/23
【摘要】 一,表锁GaussDB(DWS) 支持的表锁级别很多,从最低的1级到最高的8级:1级锁,AccessShareLockSELECT语句申请AccessShareLock,只与8级锁冲突,只会阻塞DDL等语句。2级锁,RowShareLockSELECT FOR SHARE/UPDATE语句申请RowShareLock,与7/8级锁冲突。3级锁,RowExclusiveLockINSERT/U...

1. 前言

  • 适用版本:【8.1.3(及以上)】

主要介绍GaussDB(DWS)中的锁类型及使用方式,包括SpinLock, LWLock, RegularLock,并详细介绍其中的RegularLock用法。

2. SpinLock

  • 称为自旋锁,一般依赖于硬件支持,需要CPU支持TAS(test-and-set)指令集;

  • 由于没有cpu上下文切换,性能高,主要用于临界区很短的场景,能快速释放锁,如几个指令内的内存状态修改和计算;

  • 最多只有一个持有者,如未能获取到锁,则cpu busy做轮询检查直到拿到(超时后会PANIC退出);

  • 没有等待队列和死锁检测;

3. LWLock

  • 称为轻量级锁,只存在两种锁类型(LWLockMode):共享锁(Shared)和排它锁(Exclusive),当无法获取到锁时,会进行阻塞等待状态;

  • 原生PG不提供死锁检测,DWS自己支持了死锁检测;

  • 加锁解锁对外部用户透明,使用完一般应该立即主动释放,不等事务结束;

4. RegularLock

  • 称为常规锁,底层使用hash表,持锁时间可以较长,有死锁检测和等待队列,事务结束时会自动释放;

  • 可细分为表锁,事务锁,文件扩展锁,咨询锁等;

4.1 表锁

GaussDB(DWS) 支持的表锁级别很多,原生PG支持从最低的1级到最高的8级,另外DWS在8.2.1版本(及以上)中还增加了9级锁,各锁级别含义如下:

  • 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级锁与所有锁都冲突;

  • 9级锁,UpdateExclusiveLock 仅(auto)vacuum中使用,为了支持与(auto)analyze操作并行;

详细的锁冲突矩阵图如下所示:

4.2 其他锁

除了表锁,GaussDB(DWS) 中还有很多其他的锁,下面列出一些常用的锁:

  1. 事务锁 写事务会获取一个事务号,并且会以这个事务号申请一个事务锁,锁级别是7级锁ExclusiveLock。 事务锁用于控制记录的并发修改,比如,两个事务先后修改同一条记录,在前一个事务未结束之前,后一个事务会等待在前一个事务的事务锁上。

  2. 记录锁 当出现并发更新冲突时,冲突的事务会申请记录锁,锁级别是7级锁ExclusiveLock。 记录锁主要是提高等待事务的优先级,在更新事务结束后,让持有记录锁的事务第一个被唤醒。

  3. 扩展锁 文件扩展时,会申请扩展锁,扩展锁的锁级别是7级锁ExclusiveLock。 表、索引、fsm、vm等文件扩展时都会申请扩展锁。

  4. 分区锁 分区锁是专门针对分区表的,分区锁的意义与表锁差不多,锁级别从1-8都有。

4.3 用户自定义锁

也叫咨询锁(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)
  1. 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标识的相关函数表示尝试申请锁,如果申请不到,直接返回,不需锁等待;

5. 如何查看锁等待

通过查询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,同时对这条记录进行更新,更新顺序如下:

  1. 对于session1,查看pg_locks,如下图所示

  1. 对于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级事务锁冲突,需要锁等待;

6. 总结

本文介绍了GaussDB(DWS)中的几种锁类别,并结合锁等待视图进行了演示,观测锁持有情况。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。