• PostgreSQL中所的锁


           为了确保复杂的事务可以安全地同时运行,PostgreSQL提供了各种级别的锁来控制对各种数据对象的并发访问,使得对数据库关键部分的更改序列化。事务并发运行,直到它们尝试获取互相冲突的锁为止(比如两个事务更新同一行时)。当多个事务同时在数据库中运行时,并发控制是一种用于维持一致性和隔离性的技术,在PostgreSQL中,使用快照隔离Sanpshot Isolation (简称SI) 来实现多版本并发控制,同时以两阶段锁定 (2PL) 机制为辅。在执行DDL时使用2PL,在执行DML时使用SI

             在PostgreSQL中,最主要的是表级锁与行级锁,此外还有页锁、咨询锁

    常用概念

    系统锁与事务锁

    原子操作:PostgreSQL为了支持无锁编程,提供了系列的原则操作,包括内存屏障,CAS(Compare And Swap),TAS(Test And Set)等

    自旋锁(Spin lock):是一种和硬件结合的互斥锁,它借用了硬件提供的原子操作原语来对一些共享变量进行封锁,通常适用于临界区比较小的情况

    轻量锁(Lightweight lock):PostgreSQL中进程需要对共享内存进行频繁的读写操作,轻量锁主要是保护这些共享内存中的数据结构。它是一种读写锁,有共享排它两种模式

    常规锁(Regular lock):对数据库对象加锁,PostgreSQL两阶段锁就是借助常规锁实现的。根据封锁对象的不同,他有分成了不同粒度,如对表、页面、元祖、事务ID等分别加锁。已最常见的表锁为例,当不同的事务操作一个表时,会尝试通过表的Oid来构造LockTag,这样每个数据库对象都会有一个唯一标识,然后根据这个唯一的标识到锁表中申请锁。postgreSQL数据库将常规锁分层了8个不同的等级,不同的操作需要使用不同等级的常规锁。

    常规锁的级别

    锁模式说明
    AccessShareLock(1)当对一个对象进行查询(select)操作,会申请该类型的锁,该锁是最低级别的锁,相当于读写锁中的共享锁
    RowShareLock(2)当查询指定FOR UPDATE/SHARE时,会申请该类型的锁
    RowExclusiveLock(3)当对数据对象做增删改操作是,会申请该类型的锁,INSERT、DELETE、UPDATE
    ShareUpdateExclusiveLock(4)VACUUM(non-FULL)、ANALYZE、CREATE INDEX CONCURRENTLY, ALTER TABLE
    ShareLock(5)主要用于创建索引时申请该类型的锁, CREATE INDEX
    ShareRowExclusiveLock(6)和ExclusiveLock相似,但和RowShareLock兼容。
    CREATE TRIGGER, ALTER TABLE
    ExclusiveLock(7)和AccessExClusiveLock类似,但和最低级别的读锁AccessShareLock兼容
    AccessExclusiveLock(8)在对元数据(系统表)做DDL操作时,会申请该类型的锁,AccessExclusiveLock与其他所有的锁模式都不相容
    DROP,TRUNCATE,VACUUM FULL, LOCK TABLE

    两阶段锁

    对象锁

    对象锁是在共享内存中的,受到两个参数值的限制:max_locks_per_transaction×max_connections

    对象锁可以通过pg_locks这个视图来查询

     

    1. SELECT
    2. l.pid,
    3. a.datname AS database,
    4. c.relname AS table,
    5. l.mode AS lock_mode,
    6. l.granted AS granted,
    7. a.usename AS username,
    8. a.query AS query
    9. FROM
    10. pg_locks l
    11. JOIN
    12. pg_stat_activity a ON l.pid = a.pid
    13. JOIN
    14. pg_class c ON l.relation = c.oid

           如果资源已经锁定在不兼容的模式中,那么试图获取锁的事务将排队等待,直到释放锁。等待事务不消耗处理器资源:涉及的后端进程«休眠»,当资源空闲时被操作系统唤醒

    对象类型

    • relation
    • transactionid/virtualxid
    • tuple
    • extend
    • object
    • page
    • advisory

    对象级别的锁

    行锁

    行锁是如何实现的?

    问题

    HeapTupleSatisfiesMVCC中的HEAP_IS_LOCKED是干什么的?

    为什么HEAP_IS_LOCKED就返回true?

    调用栈

    • HEAP_XMAX_SHARED_LOCK
    • HEAP_XMAX_EXCL_LOCK
    • heap_lock_tuple
    • ExecLockRows

    heap_lock_tuple的逻辑

    1. HeapTupleSatisfiesUpdate:
      HeapTupleBeingUpdated:已插入,正在被修改,还没有提交。
      多个事务在lock元组,而且至少有一个在运行
      仅仅有一个事务在修改元组,但还没有提交
    2. 拿锁,修改pg_multixact, 修改flag, 放锁

    tuple锁

    PostgreSQL中的行锁

    转载文章:PostgreSQL中所的锁 - 知乎

  • 相关阅读:
    【Spring Boot】Spring Boot源码解读与原理剖析
    codeigniter 4.1.3 gadget chain
    【每日十分钟前端】基础篇19,普通函数、箭头函数、构造函数的区别
    【新知实验室】腾讯云TRTC初体验
    MongoDB环境搭建
    C++回顾录02
    Python数据类型底层、推导、生成器、迭代器、装饰器
    霍夫曼树(Huffman Tree)
    C++面试八股文:用过std::set/std::map吗?
    【C++】C/C++内存管理
  • 原文地址:https://blog.csdn.net/qq_36535820/article/details/134525383