注意PostgreSQL“隐式”锁请求
我们在使用数据库时,经常遇到锁等待的事情。例如一个用户在更新一条记录时,另一个会话要更新同一条记录就需要等待。这种锁等待是比较显而易见的,有一些锁等待你可能会觉得匪夷所思。下面就由DBA+社群联合发起人周正中,跟大家聊聊这些“隐式”锁请求。
专家简介
周正中
网名:德哥@Digoal
DBA+社群联合发起人
PostgreSQL中国社区发起人之一,负责杭州分会,兼任社区CTO一职。曾就职于斯凯网络,负责数据库部门。现就职于阿里巴巴,负责RDS PG内核组事务。
例如:
会话A:
会话B:
select * from pg_get_indexdef('test_pkey'::regclass); -- 查询索引的定义
如果test_pkey是test的一个索引,它会进入等待状态。
我们来跟踪一下
首先请按照 http://blog.163.com/digoal@126/blog/static/163877040201422083228624 提供的方法开启LOCK DEBUG。
会话A:
会话B:
等待中。
使用 https://github.com/digoal/pgsql_admin_script/blob/master/generate_report.sh 提供的方法可以查询到锁等待如下:
此时提交或回归会话A,然后会话B可以继续:
正常情况下,查询索引定义如果没有被堵塞,观察到的锁是这样的:
还有很多获得对象定义的函数,使用时需要注意。
例如:
获取规则定义也要请求表的AccessShareLock。
会话A:
会话B:
pg_get_viewdef也有这个问题,需要获得视图引用的表的AccessShareLock。
另外再提供一个需要注意的点,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社群】平台的文章,阅读量超过1000,该文章作者可获得赠书一本。大家如有好的干货文章也可以向我们的订阅号投稿,投稿邮箱:1017465571@qq.com。近期赠书有:白鳝《思想的天空》、杨志洪《Oracle核心技术》……
小编精心为大家挑选了近日最受欢迎的几篇热文:
回复001,看丁俊的《【重磅干货】看了此文,Oracle SQL优化文章不必再看!》;
回复002,看《灾备故障上了红头文件,容灾技术到底哪家强?》;
回复003,看吕海波的《去不去O,谁说了算?》;
回复004,看胡怡文《PG,一道横跨oltp到olap的梦想之桥》;
回复005,看付新《达梦专家解读:国产数据库也疯狂》;
回复006,看郭耀龙《假事务之名,深入研究UNDO与REDO》;
回复007,看宋日杰《Oracle后台专家解决library cache锁争用的终极武器》;
回复008,看周俊《被埋没的SQL优化利器——Oracle SQL monitor》。
DBA+社群是全中国最大的涵盖各种数据库、中间件及架构师线条的微信社群!有100+专家发起人,建有15大城市微信群,6大专业产品群,多达10000+跨界DBA加入队伍。每天1个热议话题,每周2次线上技术分享,不定期线下聚会与原创专家团干货分享,更多精彩,欢迎关注dbaplus微信订阅号!
扫码关注
DBAplus社群
超越DBA圈子,连接的不仅仅是DBA