Todos os produtos
Search
Central de documentação

Hologres:Locks: types,behavior,and troubleshooting

Última atualização: Jun 28, 2026

Os locks garantem o isolamento de transações durante a execução de SQL. O Hologres utiliza tanto locks de Frontend (FE) quanto locks de Backend (BE), cada um com tipos, escopos e comportamentos de conflito distintos. Este tópico explica como esses locks funcionam e como solucionar problemas relacionados.

Contexto

Quando uma consulta é iniciada no Hologres, ela segue o caminho mostrado na figura a seguir.Query链路 O Frontend analisa a consulta, o Query Engine gera um plano de execução e o Storage Engine lê os dados. Dois tipos de locks estão envolvidos nesse processo.

  • Locks de Frontend (FE)

    O Frontend é a camada de acesso e é compatível com o protocolo PostgreSQL; portanto, seus locks também são compatíveis com alguns locks do PostgreSQL. Os locks de FE gerenciam os metadados do FE.

  • Locks de Backend (BE)

    O BE refere-se ao Query Engine e ao Fixed Plan. Ele utiliza locks próprios do Hologres, que gerenciam o schema e os dados do Storage Engine.

Alterações no comportamento dos locks

  • A partir do Hologres V2.0, um mecanismo sem lock é ativado por padrão no Frontend (FE). Isso significa que, se surgir um conflito entre uma instrução DDL e uma instrução DQL na mesma tabela (por exemplo, uma nova consulta enviada enquanto uma operação DDL na Tabela A está em andamento), a nova solicitação DQL falhará imediatamente. Para permitir que novas solicitações DQL aguardem a liberação do lock em vez de falhar imediatamente, desative o parâmetro GUC:

    ALTER database <db_name> SET hg_experimental_disable_pg_locks = off;
  • Desde o Hologres V2.1, o carregamento em massa de dados em uma tabela sem chave primária foi otimizado para adquirir apenas um lock de nível de linha em vez de um lock de nível de tabela.

Tipos de locks

  • Locks de FE

    A camada de acesso do Hologres, o Frontend, é compatível com o PostgreSQL; portanto, os locks nessa camada também são compatíveis com o PostgreSQL. O PostgreSQL fornece três modos de lock para controlar o acesso simultâneo aos dados: locks de nível de tabela, locks de nível de linha e advisory locks. O Hologres é compatível com locks de nível de tabela e advisory locks.

    Nota

    O Hologres não oferece suporte a bloqueio explícito ou UDFs relacionadas a advisory locks.

    • Locks de nível de tabela

      • Modos

        Um lock de nível de tabela é um bloqueio em toda a tabela. Os modos são os seguintes.

        Modo de lock

        Descrição

        Observação

        ACCESS SHARE

        O comando SELECT adquire um lock deste modo nas tabelas referenciadas.

        N/A

        ROW SHARE

        Apenas os comandos SELECT FOR UPDATE e SELECT FOR SHARE adquirem este lock na tabela de destino. Tabelas que não são de destino (como outras tabelas em um JOIN) adquirem apenas um lock ACCESS SHARE.

        O Hologres não oferece suporte aos comandos SELECT FOR UPDATE e SELECT FOR SHARE; portanto, este modo de lock não se aplica.

        ROW EXCLUSIVE

        Comandos DML que modificam dados, como UPDATE, DELETE e INSERT, adquirem este lock.

        Considere isso em conjunto com os locks de BE.

        SHARE UPDATE EXCLUSIVE

        Um lock que evita conflitos entre VACUUM e alterações simultâneas de schema. Os seguintes comandos adquirem este lock:

        • lazy VACUUM (não inclui Vacuum Full).

        • ANALYZE.

        • CREATE INDEX CONCURRENTLY.

          Nota

          Ao executar este comando, o Hologres não adquire um lock SHARE UPDATE EXCLUSIVE. Em vez disso, adquire um lock SHARE, semelhante ao CREATE INDEX não simultâneo.

        • CREATE STATISTICS (sem suporte no Hologres).

        • COMMENT ON.

        • ALTER TABLE VALIDATE CONSTRAINT (sem suporte no Hologres).

        • ALTER TABLE SET/RESET (storage_parameter). O Hologres suporta apenas o uso deste comando para definir suas próprias propriedades estendidas e a propriedade nativa do PostgreSQL autovacuum_enabled. Definir essas propriedades não adquire nenhum lock de tabela. Modificar certos outros parâmetros de armazenamento integrados do PostgreSQL adquire este lock. Para obter mais informações, consulte ALTER TABLE.

        • ALTER TABLE ALTER COLUMN SET/RESET options.

        • ALTER TABLE SET STATISTICS (sem suporte no Hologres).

        • ALTER TABLE CLUSTER ON (sem suporte no Hologres).

        • ALTER TABLE SET WITHOUT CLUSTER (sem suporte no Hologres).

        Atenção especial ao comando ANALYZE.

        SHARE

        Apenas um CREATE INDEX não simultâneo adquire este lock.

        Nota

        No Hologres, a criação de um índice JSON adquire este lock.

        Atenção especial ao comando CREATE INDEX (para criação de índices relacionados a JSON).

        SHARE ROW EXCLUSIVE

        Um lock que impede modificações simultâneas de dados. Os seguintes comandos adquirem este lock:

        • CREATE COLLATION (sem suporte no Hologres).

        • CREATE TRIGGER (sem suporte no Hologres).

        • Alguns comandos ALTER TABLE:

          • DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER (sem suporte no Hologres).

          • ADD table_constraint (sem suporte no Hologres).

        O Hologres não oferece suporte a comandos que adquirem este lock; portanto, este modo de lock não se aplica.

        EXCLUSIVE

        Apenas o comando REFRESH MATERIALIZED VIEW CONCURRENTLY adquire este lock.

        O Hologres não oferece suporte ao comando REFRESH MATERIALIZED VIEW CONCURRENTLY; portanto, este modo de lock não se aplica.

        ACCESS EXCLUSIVE

        Um lock necessário para acesso totalmente exclusivo, que entra em conflito com todos os outros locks. Os seguintes comandos adquirem este lock:

        • DROP TABLE

        • TRUNCATE TABLE

        • REINDEX (sem suporte no Hologres).

        • CLUSTER (sem suporte no Hologres).

        • VACUUM FULL

        • REFRESH MATERIALIZED VIEW (without CONCURRENTLY) (sem suporte no Hologres).

        • LOCK: o comando LOCK explícito. Se nenhum tipo específico de lock for especificado, este lock será adquirido por padrão. (Sem suporte no Hologres).

        • ALTER TABLE: Além das formas de ALTER TABLE que adquirem locks específicos conforme mencionado acima, outras formas de ALTER TABLE adquirem este lock por padrão.

        Este é um lock crítico. Operações DDL no Hologres adquirem este lock, que entra em conflito com todos os outros tipos de lock.

      • Timeout

        Os locks de FE não possuem um timeout padrão. Defina explicitamente um timeout para evitar tempos de espera de lock excessivamente longos. Consulte Gerenciar consultas.

      • Relações de conflito

        A tabela a seguir mostra as relações de conflito entre os modos de lock. Um conflito significa que uma operação deve esperar que outra libere seu lock.

        Nota

        Supported indica ausência de conflito. Not supported indica um conflito.

        Modo de lock solicitado

        ACCESS SHARE

        ROW SHARE

        ROW EXCLUSIVE

        SHARE UPDATE EXCLUSIVE

        SHARE

        SHARE ROW EXCLUSIVE

        EXCLUSIVE

        ACCESS EXCLUSIVE

        ACCESS SHARE

        Supported

        Supported

        Supported

        Supported

        Supported

        Supported

        Supported

        Not supported

        ROW SHARE

        Supported

        Supported

        Supported

        Supported

        Supported

        Supported

        Not supported

        Not supported

        ROW EXCLUSIVE

        Supported

        Supported

        Supported

        Supported

        Not supported

        Not supported

        Not supported

        Not supported

        SHARE UPDATE EXCLUSIVE

        Supported

        Supported

        Supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        SHARE

        Supported

        Supported

        Not supported

        Not supported

        Supported

        Not supported

        Not supported

        Not supported

        SHARE ROW EXCLUSIVE

        Supported

        Supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        EXCLUSIVE

        Supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        ACCESS EXCLUSIVE

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

        Not supported

    • Advisory lock

      Os advisory locks têm significados definidos pela aplicação. Na maioria dos cenários de negócios do Hologres, não é necessário prestar atenção extra a eles.

  • Locks de BE

    • Categorias

      No Hologres, os locks de BE são categorizados da seguinte forma:

      Categoria de lock

      Introdução aos locks

      Exclusive(X)

      Um lock exclusivo (ou mutex lock) é adquirido quando uma transação precisa modificar dados, como com comandos DML como DELETE, INSERT ou UPDATE. Um lock exclusivo só pode ser concedido se não existirem outros locks compartilhados ou exclusivos no recurso. Uma vez adquirido, nenhum outro lock pode ser colocado nesse recurso.

      Shared(S)

      Um lock compartilhado é solicitado quando uma transação precisa ler dados, impedindo que outras transações modifiquem os dados lidos. Vários locks compartilhados podem coexistir no mesmo recurso, permitindo que comandos DQL sejam executados simultaneamente porque não alteram o recurso.

      Intent(I)

      Um intent lock indica uma estrutura de bloqueio hierárquica, permitindo que vários intent locks coexistam no mesmo recurso. Após a aquisição de um intent lock, um lock exclusivo não pode mais ser concedido para esse recurso. Por exemplo, quando uma transação solicita um lock exclusivo em uma linha, ela também adquire um intent lock na tabela, impedindo que outras transações obtenham um lock exclusivo na tabela.

    • Timeout

      O timeout padrão para locks de BE é de 5 minutos.

    • Relação de conflito

      As relações de conflito para locks de BE são as seguintes. Um conflito significa que uma operação deve esperar que outra libere seu lock.

      Nota

      Supported indica ausência de conflito. Not supported indica um conflito.

      Operação

      DROP

      ALTER

      SELECT

      UPDATE

      DELETE

      INSERT (incluindo INSERT ON CONFLICT)

      DROP

      Not supported

      Not supported

      Not supported

      Not supported

      Not supported

      Not supported

      ALTER

      Not supported

      Not supported

      Supported

      Not supported

      Not supported

      Not supported

      SELECT

      Not supported

      Supported

      Supported

      Supported

      Supported

      Supported

      UPDATE

      Not supported

      Not supported

      Supported

      Not supported

      Not supported

      Not supported

      DELETE

      Not supported

      Not supported

      Supported

      Not supported

      Not supported

      Not supported

      INSERT (incluindo INSERT ON CONFLICT)

      Unsupported

      Not supported

      Supported

      Not supported

      Not supported

      Not supported

Escopos dos locks

O escopo de um lock varia de acordo com a categoria.

  • Locks de FE

    Os locks de FE afetam apenas objetos de tabela, não os dados da tabela. Um lock é adquirido ou bloqueado. Estar bloqueado indica um conflito de lock, o que significa que a operação está aguardando o lock.

  • Locks de BE

    Os locks de BE afetam os dados da tabela ou o schema. Seus escopos são os seguintes:

    • Locks de dados de tabela: Adquirem um lock em todos os dados de uma tabela. A aquisição simultânea por várias tarefas pode causar atrasos na espera pelo lock.

    • Lock de dados de linha: Bloqueia uma linha inteira, resultando em maior eficiência de execução. Consultas aceleradas pelo Fixed Plan utilizam locks de dados de linha ou locks de schema de tabela.

    • Lock de schema de tabela: Bloqueia o schema da tabela. É adquirido por transações que precisam ler ou modificar o schema da tabela. A maioria das transações adquire um lock de schema. Tipos atuais de lock de schema:

      • SchX: Schema Exclusive Lock, usado para instruções DDL. Atualmente, suporta apenas o comando DROP TABLE.

      • SchU: Schema Update Lock, usado para instruções DDL que modificam a estrutura da tabela, incluindo os comandos ALTER TABLE e set_table_property.

      • SchE: Schema Existence Lock, usado para instruções DML e DQL para impedir que uma tabela seja excluída durante operações de leitura e gravação.

      Nota
      • O SchU fornece controle granular para locks DDL, permitindo que o DQL seja executado normalmente durante operações ALTER TABLE sem espera. O SchX é o lock exclusivo DDL de granulação mais grossa, para o qual todas as operações DDL, DML e DQL devem esperar.

      • Se uma consulta demorar muito para iniciar, ela pode estar aguardando locks de BE.

Os escopos de lock para comandos comuns no Hologres são os seguintes. Supported indica que a operação adquire o lock especificado.

Nota
  • Gravações, atualizações e exclusões que não usam um Fixed Plan são consideradas operações Bulkload.

  • O comando CREATE INDEX refere-se à criação de índices relacionados a JSON.

  • Os comandos DDL incluem CREATE, DROP, ALTER, entre outros.

Operação / Escopo do lock

Lock de nível de tabela

Lock de dados de tabela

Lock de dados de linha

Lock de schema de tabela

CREATE

Supported

N/A

DROP

Supported

Nota

Depois que o comando DROP adquire um lock, nenhum outro comando pode ser executado nessa tabela. Esses comandos aguardarão a liberação do lock. Ao detectar que a tabela foi excluída, eles falharão.

N/A

N/A

Supported

Nota

Entra em conflito com todas as outras operações.

ALTER

Supported

Nota

Igual ao comando DROP.

N/A

N/A

Supported

Nota

É possível executar comandos SELECT na tabela enquanto ela mantém um Table Schema Lock.

SELECT

Supported

Nota

Enquanto o lock de tabela estiver mantido, comandos INSERT, UPDATE e DELETE podem ser executados na tabela. Entra em conflito apenas com locks DDL.

N/A

N/A

Supported

Nota

Durante a execução de um comando SELECT, todas as outras operações podem ser realizadas, exceto o comando DROP.

INSERT (incluindo INSERT ON CONFLICT)

Supported

Nota

O comando INSERT entra em conflito com CREATE INDEX e DDL.

  • No Hologres V2.0 e anteriores, o bulkload adquire um lock de dados de tabela.

  • A partir do Hologres V2.1, apenas o bulkload em tabelas com chave primária adquire um lock de dados de tabela.

Nota

O Bulkload entra em conflito com o Fixed Plan.

Se a operação for realizada via Fixed Plan, um lock de dados de linha será adquirido.

A partir do Hologres V2.1, o bulkload para uma tabela sem chave primária também adquire apenas um lock de dados de linha.

Nota
  • O Hologres V2.0 e anteriores não suportam gravações em lote simultâneas e gravações em tempo real aceleradas pelo Fixed Plan.

  • A partir do Hologres V2.1, há suporte para gravações em lote simultâneas e gravações em tempo real aceleradas pelo Fixed Plan em tabelas sem chave primária.

Supported

Nota

Entra em conflito com DDL e DML.

UPDATE

Supported

Nota

Este lock entra em conflito com locks CREATE INDEX e DDL.

Supported

Nota

Entra em conflito com DDL e DML.

DELETE

Supported

Nota

Este lock entra em conflito com locks CREATE INDEX e DDL.

Supported

Nota

Entra em conflito com DDL e DML.

Comportamento de locks relacionados a transações

Atualmente, o Hologres suporta transações explícitas apenas para DDL. Não há suporte para transações puramente DML ou transações mistas de DDL e DML.

  • O Hologres não suporta subtransações aninhadas.

  • Embora transações puramente DML sejam aceitas sintaticamente, elas não suportam efetivamente commits e rollbacks atômicos.

    No exemplo DML a seguir, mesmo que o INSERT seja bem-sucedido, os dados inseridos não sofrerão rollback se o UPDATE subsequente falhar.

    begin;
    insert into t1(id, salary) values (1, 0);
    update t1 set salary = 0.1 where id = 1;
    commit;
  • Transações puramente DDL funcionam conforme o esperado.

    Se qualquer comando DDL na transação falhar, toda a transação sofrerá rollback. Por exemplo, no código a seguir, se o comando ALTER falhar, as operações anteriores CREATE e DROP serão revertidas.

    begin;
    create table t1(i int);
    drop table if exists t2;
    alter table t1 add column n text;
    commit;
  • Transações com uma mistura de comandos DDL e DML são proibidas.

    No exemplo a seguir, quando uma transação contém comandos DDL e DML, o comando DML reporta um erro.

    begin;
    create table t1(i int);
    update t1 set i = 1 where i = 1;
    -- DML statement error
    ERROR:  UPDATE in ddl transaction is not supported now.
  • Os locks adquiridos por qualquer comando em uma transação explícita são liberados apenas quando toda a transação termina (por commit ou rollback).

    No exemplo a seguir, uma operação ALTER em uma tabela pai adquire locks ACCESS EXCLUSIVE tanto na tabela pai (login_history) quanto na tabela filha (login_history_202001). Esses locks não são liberados imediatamente após o término do comando. Eles são mantidos até que o COMMIT final seja executado (independentemente de sucesso ou falha). Se o COMMIT não for executado, os locks serão mantidos indefinidamente, e qualquer outra operação DDL nesta tabela será bloqueada e reportará um erro.

     -- suppose we have three tables
    create table temp1(i int, t text);
    create table login_history(ds text, user_id bigint, ts timestamptz) partition by list (ds);
    create table login_history_202001 partition of login_history for values in ('202001');
    
    begin;
    alter table login_history_s1 add column user_id bigint;
    drop table temp1;
    create table tx2(i int);
    commit;

Solucionar problemas de locks de FE

Siga estas etapas para verificar e resolver locks de FE:

  1. Se uma consulta demorar muito, verifique o campo wait_event_type para ver se a consulta está aguardando um lock.

    No exemplo de comando a seguir, se o campo wait_event_type no resultado for Lock, isso indica que a consulta está aguardando um lock de FE.

    -- Hologres V2.0 and later:
    select query,state,query_id,transaction_id,pid,wait_event_type,wait_event,running_info,extend_info FROM hg_stat_activity where query_id = 200640xxxx;
    -- The following result is returned:
    ----------------+----------------------------------------------------------------
    query           | drop table test_order_table1;
    state           | active
    query_id        | 200640xxxx
    pid             | 123xx
    transaction_id  | 200640xxxx
    wait_event_type | Lock
    wait_event      | relation
    running_info    | {"current_stage":{"stage_duration_ms":47383,"stage_name":"PARSING"},"fe_id":1,"warehouse_id":0}+
                    |
    extend_info     | {}                                                                                                                                           +
    
    -- Hologres V1.3 and earlier:
    select datname, pid, application_name, wait_event_type, state,query_start, query from pg_stat_activity where backend_type in ('client backend');
    -- The following result is returned:
    ----------------+----------------------------------------------------------------
    datname           | holo_poc
    pid               | 321xxx
    application_name  | PostgreSQL JDBC Driver
    wait_event_type   | lock
    state             | active
    query_start       |2023-04-20 14:31:46.989+08
    query             | delete from xxx
  2. Visualize o detentor do lock.

    Sintaxe:

    select * from pg_locks where pid = <pid>;

    Substitua pid pelo valor pid retornado na Etapa 1.

  3. Identifique qual processo está mantendo o lock.

    Se o resultado da Etapa 2 mostrar que a consulta atual está aguardando um lock, use o seguinte comando com o oid (Object ID) da tabela para encontrar o processo que mantém um lock nela. Um valor t (verdadeiro) na coluna granted indica que um processo está mantendo o lock.

    -- Query the process that holds the table lock.
    select pid from pg_locks where relation = <OID> and granted = 't';
  4. Identifique a consulta que mantém o lock.

    Use o PID do resultado da Etapa 3 e execute o seguinte comando para encontrar a consulta que mantém o lock.

    select * from pg_stat_activity where pid = <PID>;
  5. Libere o lock.

    Execute o seguinte comando para encerrar a consulta e liberar o lock.

    select pg_cancel_backend(<pid>);

Solucionar problemas de locks de BE

Se o campo be_lock_waiters na view hg_stat_activity contiver dados, a consulta mantém um lock ou está bloqueada por um lock de BE. Solucione o problema seguindo estas etapas.

Nota

A hg_stat_activity é suportada apenas no Hologres V2.0 e posteriores.

  • Cenário 1: A consulta atual mantém um lock e outras consultas estão aguardando sua liberação.

    Visualize a consulta que mantém o lock e as consultas bloqueadas:

    select query_id, transaction_id, ((extend_info::json)->'be_lock_waiters'->>0)::text as be_lock_waiters 
    FROM hg_stat_activity as h where h.state = 'active' and ((extend_info::json)->'be_lock_waiters')::text != '';
    
    -- The following result is returned:
    ----------------+------------------
    query_id        | 10005xxx
    transaction_id  | 10005xxx
    be_lock_waiters | 13235xxx
  • Cenário 2: Verifique qual consulta está bloqueando a consulta atual.

    Descubra qual consulta está mantendo o lock que a consulta atual aguarda.

    select query_id, transaction_id, ((extend_info::json)->'be_lock_waiters')::text as be_lock_waiters 
    FROM hg_stat_activity as h where h.state = 'active' and ((extend_info::jsonb)->'be_lock_waiters')::jsonb ? '10005xxx';
    
    -[ RECORD 1 ]---+------------------------------------------
    query_id        | 200740017664xxxx
    transaction_id  | 200740017664xxxx
    be_lock_waiters | ["200640051468xxxx","200540035746xxxx"]

Erros comuns e soluções

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

    • Possível causa: Sua consulta atingiu o timeout após 5 minutos de espera por um lock de BE. Outra consulta está mantendo um lock conflitante (neste caso, uma combinação de um SchS, um SchE e um lock Exclusivo) na mesma tabela.

    • Solução: Encontre a consulta bloqueadora e encerre-a. O ID da transação da mensagem de erro, Transaction =302xxxx, é o ID da consulta bloqueadora. Procure este ID de consulta no log de consultas lentas ou na view de consultas ativas para identificar e gerenciar o processo.

  • Erro: ERROR: The schema version update timed out because the server's current version (xxx) is older than the requested version (yyy).

    • Possível causa: Uma instrução DDL primeiro atualiza a versão do schema no FE. Se uma nova consulta chegar antes que o Storage Engine tenha aplicado a alteração, a consulta deverá esperar. A consulta falhará se essa espera exceder o timeout de 5 minutos.

    • Solução:

      • Encerre a operação DDL que mantém o lock e execute novamente sua consulta.

      • Se o problema persistir, reinicie a instância para forçar a sincronização.

  • Erro: The requested table name: xxx (id: 10, version: 26) mismatches the version of the table (id: 10, version: 28) from server.

    • Possível causa: Após uma operação DDL, o Storage Engine atualiza sua versão, mas essa alteração precisa ser replicada em todos os nós de FE. Este erro ocorre quando sua consulta se conecta a um nó de FE que ainda não sincronizou com a versão mais recente da tabela do Storage Engine.

    • Solução:

      • Tente executar a consulta novamente várias vezes. O problema geralmente é resolvido ao conectar-se a um nó de FE atualizado.

      • Se tentar novamente não funcionar após alguns minutos, reinicie a instância para limpar o estado inconsistente.

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

    • Possível causa: Este erro ocorre quando uma operação DML (como SELECT ou DELETE) tenta acessar uma tabela enquanto um comando DROP TABLE ou TRUNCATE TABLE está sendo executado nela. A consulta DML aguarda a liberação do lock DDL, mas, no momento em que é executada, a tabela ou seu índice já foi excluído.

    • Solução: Certifique-se de que nenhuma outra consulta esteja sendo executada em uma tabela antes de executar comandos DROP ou TRUNCATE nela. Coordene as operações DDL e DML para evitar acesso simultâneo.