• postgreSql执行状态与锁冲突问题排查


    • postgreSql执行状态与锁冲突问题排查

    在工作中,对于一些postgres数据库的初学者,在执行某些sql过程中,会发现一直卡住,从而不知道该如何解决,看完这篇文章,希望聪明的你能够有所收获

    • 当我们需要判断postgres数据库正在执行的sql,一般会这么做
    select * from pg_stat_activity;
    
    • 1

    pg_stat_avtivity 是一张postgresql的系统视图,它的每一行都表示一个系统进程,显示与当前会话的活动进程的信息,比如当前会话的状态和查询等,它的state字段表示当前进程的状态,总共有六种状态

    state释义
    active进程正在执行某个语句
    idle进程处于空闲状态,正在等待客户端的指令
    idle in transaction进程在处理事务的过程中
    idle in transaction(aborted)进程在处理事务的过程中,但是事务内部sql操作出现了错误
    fastpath function call后台正在执行某个快速通道函数
    disabled报告状态被禁用

    了解了进程状态后,那么和锁有什么关系呢?

    每个ddl或者dml的执行,都会拿到相关表的锁,并且不同的锁也会产生互斥操作

    • 下图是关于postgres涉及的锁以及锁之间的互斥关系

    在这里插入图片描述

    • example

    从上图中,可以看出,SELECT操作会获取到AccessShareLock ,DROP操作会获取到AccessExclusiveLock,这两个锁又是互斥的关系

    • 会话1开启事务,执行select操作
    # 会话1开启事务
    postgres=# begin;
    BEGIN
    postgres=*# select * from t1;
     id 
    ----
      1
    (1 row)
    # 此时该sql处于事务中,进行了select操作,并且没有被提交,所以会一直拿着AccessShareLock,直到事务被提交
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 查看此时t1表的锁
    postgres=# select a.locktype,a.database,a.pid,a.mode,a.relation,a.granted,b.relname from pg_locks a  join pg_class b on a.relation=b.oid where b.relname='t1';
     locktype | database |  pid   |      mode       | relation | granted | relname 
    ----------+----------+--------+-----------------+----------+---------+---------
     relation |    13295 | 440579 | AccessShareLock |    19188 | t       | t1
    (1 row)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 会话2,执行drop操作
    postgres=# drop table t1;
    
    # 此时该sql会卡住,因为drop操作会获取AccessExclusiveLock,与AccessShareLock是冲突的
    
    • 1
    • 2
    • 3
    • 查看此时t1表的锁
    postgres=# select a.locktype,a.database,a.pid,a.mode,a.relation,a.granted,b.relname from pg_locks a  join pg_class b on a.relation=b.oid where b.relname='t1';
     locktype | database |  pid   |        mode         | relation | granted | relname 
    ----------+----------+--------+---------------------+----------+---------+---------
     relation |    13295 | 440579 | AccessShareLock     |    19188 | t       | t1
     relation |    13295 | 440025 | AccessExclusiveLock |    19188 | f       | t1
    (2 rows)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 会话1,commit提交事务
    postgres=*# commit;
    COMMIT
    # 会话1的事务提交后,会发现会话2的drop操作也会相继执行,此时查看t1表,所有的锁均已经被释放
    
    • 1
    • 2
    • 3

    一般在测试环境中,大家也可以通过获取进程号,使用pg_terminate_backend(‘procpid’)函数或者 pg_cancel_backend(‘procpid’)函数结束进程

  • 相关阅读:
    一文带你读懂scala中的隐式转换
    链表之删除单链表中的重复节点
    Python的对象与类
    300道SpringCloud面试题2022(面试题及答案)
    和娃一起过暑假:一次4000+km自驾的尝试
    Ubuntu 环境配置 Minecraft 基岩版服务器
    使用遗传算法优化BP神经网络实现非线性函数拟合
    挠场的科学丨二、无线电力传送与特斯拉遗失的文件
    【C语言】利用数组处理批量数据(一维数组和二维数组)
    电子行业MES管理系统需求分析
  • 原文地址:https://blog.csdn.net/qq_44170834/article/details/126504367