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

简介: 本文介绍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轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
相关文章
|
12月前
|
存储 消息中间件 分布式计算
Hologres实时数仓在B站游戏的建设与实践
本文介绍了B站游戏业务中实时数据仓库的构建与优化过程。为满足日益增长的数据实时性需求,采用了Hologres作为核心组件优化传统Lambda架构,实现了存储层面的流批一体化及离线-实时数据的无缝衔接。文章详细描述了架构选型、分层设计(ODS、DWD、DIM、ADS)及关键技术挑战的解决方法,如高QPS点查、数据乱序重写等。目前,该实时数仓已广泛应用于运营分析、广告投放等多个场景,并计划进一步完善实时指标体系、扩展明细层应用及研发数据实时解析能力。
Hologres实时数仓在B站游戏的建设与实践
|
存储 分布式计算 MaxCompute
Hologres实时湖仓能力入门实践
本文由武润雪(栩染)撰写,介绍Hologres 3.0版本作为一体化实时湖仓平台的升级特性。其核心能力包括湖仓存储一体、多模式计算一体、分析服务一体及Data+AI一体,极大提升数据开发效率。文章详细解析了两种湖仓架构:MaxCompute + Hologres实现离线实时一体化,以及Hologres + DLF + OSS构建开放湖仓架构,并深入探讨元数据抽象、权限互通等重点功能,同时提供具体使用说明与Demo演示。
|
SQL 弹性计算 运维
Hologres计算组实例&分时弹性入门实践
本文由骆撷冬(Hologres PD)撰写,围绕Hologres计算组实例与分时弹性的入门实践展开。内容分为三部分:第一部分介绍Hologres计算组实例的原理与架构,解决负载隔离、资源浪费、大任务和运维难题;第二部分演示计算组实例的入门实践,包括管理、授权、连接及监控等操作;第三部分讲解分时弹性的使用,涵盖配置方法、成本优化及监控告警。通过具体案例与操作步骤,帮助用户更好地理解和应用Hologres的弹性计算能力。
|
12月前
|
存储 消息中间件 Java
抖音集团电商流量实时数仓建设实践
本文基于抖音集团电商数据工程师姚遥在Flink Forward Asia 2024的分享,围绕电商流量数据处理展开。内容涵盖业务挑战、电商流量建模架构、流批一体实践、大流量任务调优及总结展望五个部分。通过数据建模与优化,实现效率、质量、成本和稳定性全面提升,数据质量达99%以上,任务性能提升70%。未来将聚焦自动化、低代码化与成本优化,探索更高效的流批一体化方案。
718 12
抖音集团电商流量实时数仓建设实践
|
存储 SQL Java
Flink CDC + Hologres高性能数据同步优化实践
本文整理自阿里云高级技术专家胡一博老师在Flink Forward Asia 2024数据集成(二)专场的分享,主要内容包括:1. Hologres介绍:实时数据仓库,支持毫秒级写入和高QPS查询;2. 写入优化:通过改进缓冲队列、连接池和COPY模式提高吞吐量和降低延迟;3. 消费优化:优化离线场景和分区表的消费逻辑,提升性能和资源利用率;4. 未来展望:进一步简化用户操作,支持更多DDL操作及全增量消费。Hologres 3.0全新升级为一体化实时湖仓平台,提供多项新功能并降低使用成本。
876 1
Flink CDC + Hologres高性能数据同步优化实践
|
存储 弹性计算 运维
Hologres计算组实例&分时弹性入门实践
本文整理自 Hologres 产品团队的观秋老师关于Hologres 计算组实例&分时弹性入门实践的分享。内容主要为以下三部分: 1. Hologres 计算组实例介绍 2. 计算组实例入门实践 3. 分时弹性入门实践
368 16
|
DataWorks 关系型数据库 OLAP
云端问道5期实践教学-基于Hologres轻量实时的高性能OLAP分析
本文基于Hologres轻量实时的高性能OLAP分析实践,通过云起实验室进行实操。实验步骤包括创建VPC和交换机、开通Hologres实例、配置DataWorks、创建网关、设置数据源、创建实时同步任务等。最终实现MySQL数据实时同步到Hologres,并进行高效查询分析。实验手册详细指导每一步操作,确保顺利完成。
277 8
|
11月前
|
存储 消息中间件 OLAP
基于 Flink+Paimon+Hologres 搭建淘天集团湖仓一体数据链路
本文整理自淘天集团高级数据开发工程师朱奥在Flink Forward Asia 2024的分享,围绕实时数仓优化展开。内容涵盖项目背景、核心策略、解决方案、项目价值及未来计划五部分。通过引入Paimon和Hologres技术,解决当前流批存储不统一、实时数据可见性差等痛点,实现流批一体存储与高效近实时数据加工。项目显著提升了数据时效性和开发运维效率,降低了使用门槛与成本,并规划未来在集团内推广湖仓一体架构,探索更多技术创新场景。
1800 3
基于 Flink+Paimon+Hologres 搭建淘天集团湖仓一体数据链路
|
SQL 运维 网络安全
【实践】基于Hologres+Flink搭建GitHub实时数据查询
本文介绍了如何利用Flink和Hologres构建GitHub公开事件数据的实时数仓,并对接BI工具实现数据实时分析。流程包括创建VPC、Hologres、OSS、Flink实例,配置Hologres内部表,通过Flink实时写入数据至Hologres,查询实时数据,以及清理资源等步骤。
|
SQL 消息中间件 Kafka
Flink+Paimon+Hologres,面向未来的一体化实时湖仓平台架构设计
本文介绍了阿里云实时数仓Hologres负责人姜伟华在Flink Forward Asia 2024上的分享,涵盖实时数仓的发展历程、从实时数仓到实时湖仓的演进,以及总结。文章通过三代实时数仓架构的演变,详细解析了Lambda架构、Kafka实时数仓分层+OLAP、Hologres实时数仓分层复用等方案,并探讨了未来从实时数仓到实时湖仓的演进方向。最后,结合实际案例和Demo展示了Hologres + Flink + Paimon在实时湖仓中的应用,帮助用户根据业务需求选择合适的方案。
1695 20
Flink+Paimon+Hologres,面向未来的一体化实时湖仓平台架构设计

热门文章

最新文章

相关产品

  • 实时数仓 Hologres