使用实践:Hologres锁介绍以及排查锁

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 本文介绍Hologres中的锁机制,以提升事务的隔离性。同时介绍了如何排查锁,减少sql卡住的情况。

锁介绍

锁是一种数据库的信号量管理机制,作用是保证SQL执行上不同事务的隔离性。

事务的四个特性(ACID):

  • Atomicity:原子性,要求一个包含多个操作的事务的结果,要么全部提交,要么全部不提交;
  • Consistency:一致性,要求事务提交后,数据库从一个一致状态转化到另一个一致状态,或事务失败回滚后,数据库恢复到事务执行前的一致状态。这里举的最多的例子就是多个用户银行转账,假设这些用户的总余额是500元,那么不管如何转账,有多少并发事务执行,结束后总余额应该还是500元。
  • Isolation:隔离性,要求多个事务并发执行时,一个事务不会看到其他事务的中间结果。
  • Durability:持久性,要求事务提交后,该事务对数据库的更改就持久化保存在数据库中;

当一个query发起时,在Hologres中其经过的链路如下:Frontend解析SQL,Query Engine生成执行计划等,然后Storage Engine读取数据,整个链路的锁有两种:

  • FE Locks(前端锁):Frontend为接入层,兼容Postgres协议,因此锁也会兼容Postgres的部分锁,主要用来管理FE元数据信息。
  • BE Locks(后端锁):Backend是指Query Engine和Fixed Plan,将会享有Hologres自带的锁,主要用于管理Storage Engine的schema和数据

锁1.png


下面将会对Hologres两种锁的具体介绍。


FE Locks

Hologres接入层Frontend兼容PostgreSQL,因此在接入层的锁与PG兼容。PostgreSQL提供了几种锁模式来控制并发的数据访问:Table-level Lock,Row-level Lock,Advisory Lock。 目前Hologres兼容的是Table-level Lock和Advisory Lock

说明:Hologres目前不支持显示的设置锁命令以及Advisory Lock相关的 UDF

Table-level Locks

1、锁分类

Table-level Lock是指表锁,表锁包含的锁种类有:

锁分类

锁介绍

备注

ACCESS SHARE

一般情况下只有 SELECT 命令会获取相关表的这个锁

ROW SHARE

只有 SELECT FOR UPDATESELECT FOR SHARE 这两个命令需要获取目标表的这个锁,非目标表(比如 JOIN 关联的其他表)仅获取 ACCESS SHARE 锁

Hologres并不支持这两个命令,因此无需额外关注

ROW EXCLUSIVE

UPDATE,DELETE,以及 INSERT 这种修改数据的命令需要获取这个锁

需要结合BE Locks一起关注

SHARE UPDATE EXCLUSIVE

为了防止 vacuum 和并发的 schema 变更发生冲突的锁,需要拿这个锁的命令:

    • lazy VACUUM 即:非 vacuum full
    • ANALYZE
    • CREATE INDEX CONCURRENTLY:Hologres 使用这个命令时不会拿这个 SHARE UPDATE EXCLUSIVE 锁,而是与非 CONCURRENTLY 的形式的 CREATE INDEX 一样会拿 SHARE 锁,即拿CREATE INDEX非 CONCURRENTLY
    • CREATE STATISTICS: Hologres 不支持
    • COMMENT ON
    • ALTER TABLE VALIDATE CONSTRAINT: Hologres 不支持
    • ALTER TABLE SET/RESET (storage_parameter): Hologres 仅支持使用这个命令设置自己扩展的属性,以及 PG 原生的 autovacuum_enabled 属性, 不支持设置其他属性;且设置上述属性时 不会 获取表的任何锁。 修改 PostgreSQL 内置的其他某些 storage parameter 需要拿这个锁,详细见ALTER TABLE
    • ALTER TABLE ALTER COLUMN SET/RESET options
    • ALTER TABLE SET STATISTICS: Hologres 不支持
    • ALTER TABLE CLUSTER ON: Hologres 不支持
    • ALTER TABLE SET WITHOUT CLUSTER: Hologres 不支持

重点关注analyze命令

SHARE

只有 concurrently 的 create index 需要这个锁

关注create index命令

SHARE ROW EXCLUSIVE

为了防止并发的数据修改的锁,需要拿这个锁的命令:

    • CREATE COLLATION: Hologres 不支持
    • CREATE TRIGGER: Hologres 不支持
    • 以及部分 ALTER TABLE:
      • DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER: Hologres 不支持
      • ADD table_constraint: Hologres 不支持

Hologres 不支持这个命令,无需关注

EXCLUSIVE

仅有 REFRESH MATERIALIZED VIEW CONCURRENTLY 命令需要这个锁

Hologres 不支持这个命令,无需关注

ACCESS EXCLUSIVE

完全独占访问需要的锁,与其他所有的锁都冲突,需要拿这个锁的命令有:

    • DROP TABLE
    • TRUNCATE TABLE
    • REINDEX: Hologres 不支持
    • CLUSTER: Hologres 不支持
    • VACUUM FULL
    • REFRESH MATERIALIZED VIEW (without CONCURRENTLY): Hologres 不支持
    • LOCK: 显示的 LOCK 命令,如果不指明具体的锁类型,默认需要这个锁;Hologres 不支持
    • ALTER TABLE: 除去上面明确提到获取特定锁的 ALTER TABLE 形式以外,其他的 ALTER TABLE 命令形式都默认获取这个锁

需要重点关注的锁,在Hologres中,执行的DDL操作都需该锁,会与其他锁冲突

2、锁超时时间

FE Locks没有默认超时时间,需要业务设置超时时间,防止锁等待时间过长。


3、锁冲突关系

锁之间的冲突关系如下表所示,其中叉号表示冲突,表示一个操作拿着锁,其余操作都需要等锁:

Requested Lock Mode

ACCESS SHARE

ROW SHARE

ROW EXCLUSIVE

SHARE UPDATE EXCLUSIVE

SHARE

SHARE ROW EXCLUSIVE

EXCLUSIVE

ACCESS EXCLUSIVE

ACCESS SHARE

X

ROW SHARE

X

X

ROW EXCLUSIVE

X

X

X

X

SHARE UPDATE EXCLUSIVE

X

X

X

X

X

SHARE

X

X

X

X

X

SHARE ROW EXCLUSIVE

X

X

X

X

X

X

EXCLUSIVE

X

X

X

X

X

X

X

ACCESS EXCLUSIVE

X

X

X

X

X

X

X

X

Advisory Locks

大部分情况业务无需额外关注,因此本文不再做详细介绍。


BE Locks

1、锁分类

在Hologres中,BE Locks锁(后端锁)分类如下:

锁分类

锁介绍

备注

Exclusive(X)

排他锁(也叫互斥锁),当事务需要修改一批或一条数据时申请排他锁,例如DML语句(DELETE、INSERT、UPDATE)。排他锁申请成功的前提是同一资源上没有其他的共享锁或排他锁,当排他锁申请成功后,锁资源上将不能同时有其他锁;

Shared(S)

共享锁,当事务需要读取一批或一条数据时申请共享锁,以免其他事务对将要读取的数据做修改。同一个资源上允许存在多个共享锁,即允许DQL之间并发执行,因为DQL不会改变资源本身。

Intent(I)

意向锁,这种类型的锁通常用于表达锁的层次结构,同一个资源上允许存在多个意向锁,当申请成功后,该资源上就不能有排他锁。例如,当事务申请一行的排他锁时,它会同时申请表的意向锁(表是比行更高层次的资源),以防止其他事务申请表的排他锁。

2、超时设置

BE Locks超时时间默认为5min,超过该时间则报错

3、锁冲突关系

BE Locks的冲突关系如下,其中叉号表示冲突,表示一个操作拿着锁,其余操作都需要等锁:

DDL分类

DROP

ALTER

SELECT

UPDATE

DETELE

INSERT

(包含INSERT ON CONFLICT)

DROP

X

X

X

X

X

X

ALTER

X

X

X

X

X

SELECT

X

UPDATE

X

X

X

X

X

DETELE

X

X

X

X

X

INSERT

(包含INSERT ON CONFLICT)

X

X

X

X

X

锁的作用范围

锁的作用范围

根据锁的分类,不同的锁作用范围不同,其中:

1、FE Locks

FE Locks只会作用在表对象上,无关数据,要么成功或者卡住,卡住就代表有锁冲突,在等待锁。

2、BE Locks

BE Locks会作用在数据或者表结构上,因此在作用范围上会分为表数据锁、行数据锁、表结构(schema)锁,其中:

  • 表数据锁:代表整个表的数据都需要拿锁,如果多个任务同时都需要拿表锁,会造成任务等待锁现象,从而任务延迟
  • 行数据锁:行锁是指整行数据拿锁,在执行效率上会更高,其中走fixed plan的Query都是行锁或者表schema
  • 表schema锁:表结构锁,当事务需要读取或修改表结构时申请Schema锁,绝大部分的事务都会申请Schema锁。目前主要有如下类型的Schema锁:
  • SchX:Schema排他锁,用于DDL语句,目前只有DROP TABLE;
  • SchU:Schema更新锁,用于修改表结构的DDL语句(ALTER TABLE或set_table_property);
  • SchS:Schema稳定锁,用于DML语句,确保数据插入期间表结构不会发生改变;
  • SchE:Schema存在锁,用户DML和DQL语句,确保读写数据期间表不会被删除;      

说明:

1、SchU是DDL锁更细粒度的管控,允许ALTER TABLE期间DQL正常运行,无需等待;SchX是最粗粒度的DDL排他锁,所有的DDL、DML、DQL都会等待;

2、如果start query耗时较长,则可能在等待BE Locks。


在Hologres中,其中常见命令作用的锁范围如下:

说明:

1、非fixed plan的写入/更新/删除都为bulkload

2、create index命令目前是指创建json相关索引,见文档

3、DDL命令包括CREATE、DROP、ALTER等

操作/锁范围

FE Locks

BE Locks

表锁

表数据锁

行数据锁

表Schema锁

CREATE

不涉及

DROP

说明:一旦DROP拿锁,无法执行其他命令,其他命令会等锁,直到发现表被drop了,则命令失败

与其他操作都冲突

ALTER

大部分行为与drop一致

拿schema更新锁,在拿锁中途可以对表进行select

SELECT

拿锁的同时可以执行insert、update、delete,只与DDL锁冲突

说明:select时除了不能Drop,其余操作都可以做

INSERT

(包含INSERT ON CONFLICT)

与create index、DDL冲突

如果是bulkload写入则拿表锁

说明:fixed plan和bulkload是相互冲突

如果是fixed plan则是行锁

说明:如果有离线写入,则不能同一个时刻同一个表既有离线又有实时fixed plan写入

与DDL冲突,与DML冲突

UPDATE

与create index、DDL冲突

与DDL冲突,与DML冲突

DELETE

与create index、DDL冲突

与DDL冲突,与DML冲突

事务相关的锁说明

Hologres 目前仅支持 DDL 的显式事务,并支持单纯的 DML 的事务,也不支持 DDL 和 DML 混合的事务:

  1. Hologres 不支持嵌套子事务
  2. 单纯的 DML 事务虽然语法上可以通过,但是实际不支持原子提交和回滚。

如下DML即使 insert 成功,如果之后的 update 失败了,insert 的数据也不会被回滚。

begin;insertinto t1(id, salary)values(1,0);update t1 set salary =0.1where id =1;commit;
  1. 纯 DDL事务可以按预期的方式工作

其中任何一行 DDL 命令失败则会整个事务被回滚。 比如下面第4行 alter 命令失败时,前面 create 和 drop 动作会被回滚。

begin;createtable t1(i int);droptable if exists t2;altertable t1 add column n text;commit;
  1. DDL 和 DML 命令混合的事务会被禁止

如下示例,当事务中包含DDL和DML时,DML命令就会报错。

begin;createtable t1(i int);update t1 set i =1where i =1;ERROR:UPDATEin ddl transaction isnot supported now.
  1. 显式事务中任何一个命令获得的锁都只会在整个事务结束(提交或回滚)时才统一释放

如下示例,当对父表做alter操作时,会同时获取父表(login_history)和子表(login_history_202001)的 ACCESS EXCLUSIVE锁, 但是这个命令执行完不会立即释放对应的锁,而是要等待最后的第 10 行的 commit 执行完(不管成功还是失败)才会释放锁。若是一直不commit,则会一直拿着锁,这时若有其他对这个表的DDL操作,则会锁表并报错。

-- suppose we have three tablescreatetable temp1(i int, t text);createtable login_history(ds text, user_id bigint, ts timestamptz) partition by list (ds);createtable login_history_202001 partition of login_history for valuesin('202001');begin;altertable login_history_s1 add column user_id bigint;droptable temp1;createtable tx2(i int);commit;


锁排查

上面介绍的两种锁,FE Locks在实际业务中是最常见也最容易引起问题的锁。当锁住时,可以通过系统表查询锁住的表以及SQL,下面将会具体介绍如何操作。

在具体的锁排查介绍之前,先了解需要用到的Postgres系统视图或者表,通过这些信息的结合来查出锁信息:

  • pg_stat_activity: 查看当前实例正在运行的SQL。
  • pg_locks: 查看当前实例正在运行中的进程或者正在等待的锁。


步骤1:查询运行时间较长的Query(可选)

通过pg_stat_activity查看运行时间较长的Query以及对应的状态,若是有Query长时间不结束,可能是这个表可能已经有其他的操作被拿锁,导致这个Query等锁。

说明:客户端可以通过参数设置 application_name,更容易排查问题。 例如在通过命令行 psql 连接时,可以通过环境变量 PGAPPNAME 来指定: PGAPPNAME=mac-sql psql -h holo-url -p 80 -d postgres

select datname, pid, application_name, wait_event_type, state, backend_xid, backend_start, xact_start, query_start, query from pg_stat_activity where backend_type in('client backend');


步骤2:查询是否有锁

通过查询是否有锁,排查长时间运行的query是否被锁住。通过以下命令查看是否有锁,f代表false,表示当前 pid 进程正在等待其他进程释放锁。

-- 查看所有在等的锁,持有的锁,及持有/等待的进程等信息select*from pg_locks where granted ='f';

若是知道哪个query运行时间比较长,可以通过pid反查是否有锁住,若是出现“f”则说明在等待锁:

select*from pg_locks where pid =<pid>;

步骤3:排查哪个进程在拿锁

通过步骤2查看知道哪个pid进程在等锁,根据其oid(即表关系)通过以下查看是否有拿锁,t代表true,代表正在拿锁。

-- 查看拿到了表锁的进程信息select pid from pg_locks where relation =<OID>and granted ='t';

步骤4:排查拿锁的query

通过步骤3结果的PID,查询真正拿锁的query

select*from pg_stat_activity where pid =<PID>;

步骤5:释放锁

找到拿锁的query之后,可以直接将query进行kill,以释放锁

select pg_cancel_backend(<pid>);

常见问题

报错:internal error: Cannot acquire lock in time, current owners: [(Transaction =302xxxx, Lock Mode = SchS|SchE|X)]."

报错原因:执行query的表有被其他query拿住BE Locks(如报错Lock Mode = SchS|SchE|X,则为Schema稳定锁、Schema存在锁、排他锁),导致query等BE Locks超时(5min)从而报错

解决办法:报错中的transaction id即Transaction =302xxxx对应query id,可以通过transaction id在慢query日志或者活跃Query中查对应拿锁的query。


报错:ERROR: Operation timed out: Wait schema version timeout.: Server current target schema version:xxx is late from request schema version: yyy

报错原因:执行DDL后,会先在Frontend(FE)节点执行,再异步在Storage Engine(SE)执行,当FE执行DDL结束后会对节点Version(版本)进行更新,若SE的DDL还没执行完成,导致SE的版本比FE的版本低,此时query会等待SE执行DDL,如果超过5min后SE仍然没有执行完成,就会报错等待schema版本超时。

解决办法:

  • 先Kill掉等锁的DML,然后重试Query
  • 重启实例(极端手段)


报错:The requested table name: xxx (id: 10, version: 26) mismatches the version of the table (id: 10, version: 28) from server

报错原因:执行DDL后,会先在Frontend(FE)单个节点执行,再异步在Storage Engine(SE)执行。SE已经完成DDL并更新版本,但是因为FE节点较多,节点间Replay未完成,导致部分FE节点的版本低于SE,而Query正好在版本较低的FE中执行,从而出现报错。

解决办法:

  • 多重试几次query
  • 若是超过几分钟还报错建议重启实例(极端手段)


报错:internal error: Cannot find index full ID: 86xxx (table id: 20yy, index id: 1) in storages or it is deleting!

报错原因:执行DROP Table或者Truncate Table时,对这个表进行DML/select,DROP/Truncate需要拿DDL大锁,导致query需要等锁,直到发现表被Drop了从而报错

解决办法:执行DROP/Truncate时,不对表进行Query

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
相关文章
|
1月前
|
SQL 分布式计算 数据挖掘
加速数据分析:阿里云Hologres在实时数仓中的应用实践
【10月更文挑战第9天】随着大数据技术的发展,企业对于数据处理和分析的需求日益增长。特别是在面对海量数据时,如何快速、准确地进行数据查询和分析成为了关键问题。阿里云Hologres作为一个高性能的实时交互式分析服务,为解决这些问题提供了强大的支持。本文将深入探讨Hologres的特点及其在实时数仓中的应用,并通过具体的代码示例来展示其实际应用。
175 0
|
3月前
|
SQL 分布式计算 数据库
畅捷通基于Flink的实时数仓落地实践
本文整理自畅捷通总架构师、阿里云MVP专家郑芸老师在 Flink Forward Asia 2023 中闭门会上的分享。
8315 15
畅捷通基于Flink的实时数仓落地实践
|
3月前
|
SQL 消息中间件 OLAP
OneSQL OLAP实践问题之实时数仓中数据的分层如何解决
OneSQL OLAP实践问题之实时数仓中数据的分层如何解决
56 1
|
6月前
|
存储 运维 监控
飞书深诺基于Flink+Hudi+Hologres的实时数据湖建设实践
通过对各个业务线实时需求的调研了解到,当前实时数据处理场景是各个业务线基于Java服务独自处理的。各个业务线实时能力不能复用且存在计算资源的扩展性问题,而且实时处理的时效已不能满足业务需求。鉴于当前大数据团队数据架构主要解决离线场景,无法承接更多实时业务,因此我们需要重新设计整合,从架构合理性,复用性以及开发运维成本出发,建设一套通用的大数据实时数仓链路。本次实时数仓建设将以游戏运营业务为典型场景进行方案设计,综合业务时效性、资源成本和数仓开发运维成本等考虑,我们最终决定基于Flink + Hudi + Hologres来构建阿里云云原生实时湖仓,并在此文中探讨实时数据架构的具体落地实践。
飞书深诺基于Flink+Hudi+Hologres的实时数据湖建设实践
|
6月前
|
存储 JSON BI
友盟+Hologres:千亿级多维分析平台建设实践
Hologres 在友盟+统计分析、营销等多个产品线使用,很好地满足了用户行为分析、人群圈选与洞察场景的多维度分析、灵活下钻、快速人群预估和圈选等分析需求,提供客户更流畅的数据查询和分析体验。
|
6月前
|
搜索推荐 Serverless BI
「FFA 动手实践」Flink+Hologres 搭建实时数仓
「FFA 动手实践」Flink+Hologres 搭建实时数仓
1045 4
「FFA 动手实践」Flink+Hologres 搭建实时数仓
|
6月前
|
存储 分布式计算 MaxCompute
Hologres RoaringBitmap实践:千亿级画像数据秒级分析
Hologres RoaringBitmap实践:千亿级画像数据秒级分析
805 2
|
3月前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版产品使用问题之使用CTAS同步MySQL到Hologres时出现的时区差异,该如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
3月前
|
SQL 关系型数据库 MySQL
实时数仓 Hologres操作报错合集之Flink CTAS Source(Mysql) 表字段从可空改为非空的原因是什么
实时数仓Hologres是阿里云推出的一款高性能、实时分析的数据库服务,专为大数据分析和复杂查询场景设计。使用Hologres,企业能够打破传统数据仓库的延迟瓶颈,实现数据到决策的无缝衔接,加速业务创新和响应速度。以下是Hologres产品的一些典型使用场景合集。
|
3月前
|
SQL 关系型数据库 测试技术
实时数仓 Hologres操作报错合集之执行Flink的sink操作时出现报错,是什么原因
实时数仓Hologres是阿里云推出的一款高性能、实时分析的数据库服务,专为大数据分析和复杂查询场景设计。使用Hologres,企业能够打破传统数据仓库的延迟瓶颈,实现数据到决策的无缝衔接,加速业务创新和响应速度。以下是Hologres产品的一些典型使用场景合集。

热门文章

最新文章

相关产品

  • 实时数仓 Hologres
  • 下一篇
    无影云桌面