注意PostgreSQL“隐式”锁请求

我们在使用数据库时,经常遇到锁等待的事情。例如一个用户在更新一条记录时,另一个会话要更新同一条记录就需要等待。这种锁等待是比较显而易见的,有一些锁等待你可能会觉得匪夷所思。下面就由DBA+社群联合发起人周正中,跟大家聊聊这些“隐式”锁请求。

 

专家简介

  

注意PostgreSQL“隐式”锁请求
周正中

网名:德哥@Digoal

DBA+社群联合发起人


PostgreSQL中国社区发起人之一,负责杭州分会,兼任社区CTO一职。曾就职于斯凯网络,负责数据库部门。现就职于阿里巴巴,负责RDS PG内核组事务。

 

 

 

例如:


会话A:


注意PostgreSQL“隐式”锁请求


会话B:


select * from pg_get_indexdef('test_pkey'::regclass);  -- 查询索引的定义

如果test_pkey是test的一个索引,它会进入等待状态。


注意PostgreSQL“隐式”锁请求


我们来跟踪一下

首先请开启LOCK DEBUG。


会话A:


注意PostgreSQL“隐式”锁请求


会话B:


注意PostgreSQL“隐式”锁请求


等待中。


注意PostgreSQL“隐式”锁请求

注意PostgreSQL“隐式”锁请求


此时提交或回归会话A,然后会话B可以继续:


注意PostgreSQL“隐式”锁请求


正常情况下,查询索引定义如果没有被堵塞,观察到的锁是这样的:


注意PostgreSQL“隐式”锁请求


还有很多获得对象定义的函数,使用时需要注意。


注意PostgreSQL“隐式”锁请求


例如:

获取规则定义也要请求表的AccessShareLock。


注意PostgreSQL“隐式”锁请求


会话A:


注意PostgreSQL“隐式”锁请求


会话B:


注意PostgreSQL“隐式”锁请求


pg_get_viewdef也有这个问题,需要获得视图引用的表的AccessShareLock。


注意PostgreSQL“隐式”锁请求


另外再提供一个需要注意的点,PG对未获得,但是在等待中的锁也在冲突列表中。


例如用户1对A表在做一个比较大的查询,另一个用户2需要对A表执行DDL,那么显然用户2的DDL无法获得排它锁在等待用户1的状态。此后,用户3或其他用户发起对A的查询请求也会被用户2堵塞,这是非常危险的,如果用户1不释放锁,那么用户2就会一直等待,同时会堵塞所有对A表的任何请求。


所以建议用户在执行DDL操作时,加一个锁超时的参数,防止出现以上情况。


set lock_timeout='1s';


还有一种autocommit的场景下,建议对需要持有大锁的SQL在执行前加上语句超时,防止长时间持锁或等待锁,在某些场景甚至可能造成拥塞,例如短连接的场景,用户可能不断发起请求,把数据库连接用完。


set statement_timeout ='1s';


以上锁DEBUG信息都可以参考src/include/storage/lock.h获得详细的描述。

本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2015-11-30

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-12-08
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-06-27
猜你喜欢
  • 2021-11-19
  • 2022-12-23
  • 2022-12-23
  • 2021-07-12
  • 2021-05-04
  • 2021-09-17
  • 2022-12-23
相关资源
相似解决方案