专栏内容:
postgresql内核源码分析
手写数据库toadb
并发编程
个人主页:我的主页
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
==================================================================
表锁介绍
当表打开,或者操作表时,都需要对表relation 进行加锁,表锁定义了8种级互斥级别,另外还有会话级表锁 session lock。
表锁的标识
- 锁类型 LOCKTAG_RELATION
- locktag的取值
locktag_field1 = dboid 当relation 为共享表时 dboid = 0
locktag_field2 = reloid
表锁相关接口
extern void LockRelationOid(Oid relid, LOCKMODE lockmode); extern void LockRelationId(LockRelId *relid, LOCKMODE lockmode); extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode); extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode); extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode); extern void LockRelation(Relation relation, LOCKMODE lockmode); extern bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode); extern void UnlockRelation(Relation relation, LOCKMODE lockmode); extern bool CheckRelationLockedByMe(Relation relation, LOCKMODE lockmode, bool orstronger); extern bool LockHasWaitersRelation(Relation relation, LOCKMODE lockmode); extern void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode); extern void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
表锁申请方式
表锁的申请,有两种,首先打开表时锁定系统字典中的记录,然后再对目标表加锁;
当然,在加锁时,会检查系统字典变更,在postgresql 就是通过invalidmessage来同步变更;
实际调用LockAcquireExtended,如果获得表锁后,首先进行invalidmessage同步处理;
首次打开表时
- 表的OID作为参数
接口有 LockRelationOid,ConditionalLockRelationOid,UnlockRelationOid
实际调用LockAcquireExtended,
用于打开表时,锁定relcache中的数据
- 表relid作为参数
接口有 LockRelationId, UnlockRelationId
实际调用LockAcquireExtended获取锁,
用于打开表时,锁定表; 解锁时UnlockRelationId比UnlockRelationOid速度要快,建议用前者
再次加表锁时
- locktag使用 relation结构初始化
接口有 LockRelation, ConditionalLockRelation, UnlockRelation;
此时表已经 open ,实际调用LockAcquireExtended,加锁时也需要检查invalidate message。
用途
在访问表、索引时,先是open处理
调用关系
- 表的打开和关闭调用关系
table_open ->relation_open ->LockRelationOid table_close ->relation_close ->UnlockRelationId
- 索引的打开和关闭调用关系 与表是类似的
index_open ->relation_open ->LockRelationOid index_close ->relation_close ->UnlockRelationId
会话锁的操作
会话锁与当前会话相关,也就是锁的持有可以跨多个事务;
释放时,调用接口释放, 或者当会话结束时会自动释放,或者是发生了ERROR级别的错误也会自动释放。
接口 LockRelationIdForSession 申请和 UnlockRelationIdForSession 释放
其中调用 LockAcquire来获取常规锁,其实也是LockAcquireExtended的也一个包装,固定了最后两个参数;会话锁的入参 LockRelId 指定了dbid, relid;
会话锁的用途
- 创建索引
在concurrent 方式创建索引时,会再次加session lock;
- 删除索引 drop index
- 重建索引 reindex
- 清理表 vacuum
结尾
非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!