谁阻塞了谁的前进--锁等待监控查询

举报
携剑笑红尘 发表于 2021/04/23 10:32:51 2021/04/23
【摘要】         在DWS中,通过锁以及多版本并发控制可以保护数据的一致性等,例如A正在查询数据,B就无法对A访问的对象执行DDL。A正在更新某条记录,B就不能删除或更新这条记录;锁本身是数据库自动管理的,同时数据库还提供了LOCK语法,允许用户自己控制锁。        当然,如果应用业务的程序逻辑设计不合理,就可能导致严重的锁等待现象,或者死锁的产生。如果你发现SQL请求大多数时候处于等待...

        在DWS中,通过锁以及多版本并发控制可以保护数据的一致性等,例如A正在查询数据,B就无法对A访问的对象执行DDL。A正在更新某条记录,B就不能删除或更新这条记录;锁本身是数据库自动管理的,同时数据库还提供了LOCK语法,允许用户自己控制锁。

        当然,如果应用业务的程序逻辑设计不合理,就可能导致严重的锁等待现象,或者死锁的产生。如果你发现SQL请求大多数时候处于等待锁的状态,那么可能出现了业务逻辑问题,需要进一步排查并调整业务逻辑。

        一、如何检查或监控锁等待呢?

                DWS提供了两个视图:

                        pg_locks:视图存储各打开事务所持有的锁信息。

                        pg_stat_activity:视图显示和当前用户查询相关的信息。

        二、如果追踪详细的锁冲突信息

                          1)    通过数据库coordinate实例日志;
                          2) 通过数据库审计日志;追踪事务中所有的SQL,分析事务之间的锁冲突
                          3) 通过SQL查看持锁,等锁的事务状态。

        三、锁的释放时机

                 大多数锁要等待事务结束后释放,某些轻量级锁(数据库自动控制)是随用随释放的。

                人工干预事务并终止操作:

                 1)     select pid from pg_stat_activity;

                         select   pg_terminate_backend(pid int)

                         描述:终止一个后台线程。 返回值类型:boolean

                         备注:如果成功,函数返回true,否则返回false。

                2)    select pid from pg_stat_activity;  

                        select   pg_cancel_backen(pid int)

                        描述:取消一个后端的当前查询。返回值类型:boolean

                         备注:如果成功,函数返回true,否则返回false。


查看当前事务锁等待查询方式:

CREATE OR REPLACE FUNCTION all_session_lock_wait_info(OUT datname name,out lock_rellist text,out h_usename name,out w_usename name,out      h_coorname name,out w_coorname name,out h_application_name text,out w_application_name text,out h_client_addr inet,out w_client_addr inet,out h_query_start date,out w_query_start date,out h_waiting boolean,out w_waiting boolean,out h_state text,out w_state text,out h_query_id bigint,out w_query_id bigint,out h_pid bigint,out w_pid bigint,out h_query text,out w_query text) 
RETURNS setof RECORD AS $$
DECLARE 
fetch_coor text;
coor_name RECORD;
table_list RECORD;
fetch_info_str text;
BEGIN
fetch_coor := 'SELECT node_name FROM pg_catalog.pgxc_node WHERE node_type=''C'' order by node_name';
FOR coor_name IN EXECUTE(fetch_coor) 
LOOP 
fetch_info_str := 'EXECUTE DIRECT ON ('||coor_name.node_name ||') ''with temp as (select pgxc_node_str()::name as coorname,ps.*,pl.relation,(select string_agg(relname,'''','''') as lock_rellist from pg_class where oid = pl.relation) from pg_stat_activity ps left join pg_locks pl on ps.pid = pl.pid where pl.relation in (select relation from pg_locks where granted=''''f'''' group by 1)) select t1.datname::name,t1.lock_rellist::text,t1.usename::name as w_usename,t2.usename::name as h_usename,t1.coorname as w_coorname,t2.coorname as h_coorname,t1.application_name::text as w_application_name,t2.application_name::text as h_application_name,t1.client_addr::inet as w_client_addr,t2.client_addr::inet as h_client_addr,t1.xact_start::timestamp as w_query_start,t2.xact_start::timestamp as h_query_start,t1.waiting::boolean as w_waiting,t2.waiting::boolean as h_waiting,t1.state::text as w_state,t2.state::text as h_state,t1.query_id::bigint as w_query_id,t2.query_id::bigint as h_query_id,t1.pid::bigint as w_pid,t2.pid::bigint as h_pid,t1.query::text as w_query,t2.query::text as h_query from temp t1,temp t2 where t1.relation=t2.relation and t1.pid <> t2.pid and t1.waiting=''''t'''' and t1.waiting <> t2.waiting;'';';
RETURN QUERY EXECUTE fetch_info_str;
END LOOP; 
END $$
LANGUAGE plpgsql;       

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。