Caso 1: INSERT em uma partição, de uma tabela, da família MergeTree*
- Atomicidade: um INSERT é concluído com êxito ou rejeitado por completo: se uma confirmação for enviada ao cliente, então todas as linhas foram inseridas; se um erro for enviado ao cliente, então nenhuma linha foi inserida.
- Consistência: se nenhuma restrição da tabela for violada, então todas as linhas de um INSERT serão inseridas e o INSERT será concluído com êxito; se as restrições forem violadas, então nenhuma linha será inserida.
- Isolamento: clientes concorrentes observam um snapshot consistente da tabela — o estado da tabela como era antes da tentativa de INSERT ou após o INSERT bem-sucedido; nenhum estado parcial é visto. Clientes dentro de outra transação têm isolamento por snapshot, enquanto clientes fora de uma transação têm nível de isolamento read uncommitted.
- Durabilidade: um INSERT bem-sucedido é gravado no sistema de arquivos antes de responder ao cliente, em uma única réplica ou em várias réplicas (controlado pela configuração
insert_quorum), e o ClickHouse pode solicitar ao SO que sincronize os dados do sistema de arquivos na mídia de armazenamento (controlado pela configuraçãofsync_after_insert). - INSERT em várias tabelas com uma única instrução é possível se houver visões materializadas envolvidas (o INSERT do cliente é feito em uma tabela que tem visões materializadas associadas).
Caso 2: INSERT em múltiplas partições de uma tabela da família MergeTree*
- Se a tabela tiver muitas partições e o INSERT abranger muitas delas, então a inserção em cada partição será transacional por si só
Caso 3: INSERT em uma tabela distribuída da família MergeTree*
- O INSERT em uma tabela distribuída não é transacional como um todo, enquanto a inserção em cada shard é transacional
Caso 4: Usando uma tabela Buffer
- inserções em tabelas Buffer não são atômicas, isoladas, consistentes nem duráveis
Caso 5: Usando async_insert
- a atomicidade é garantida mesmo que
async_insertesteja habilitado ewait_for_async_insertesteja definido como 1 (o padrão), mas, sewait_for_async_insertestiver definido como 0, a atomicidade não é garantida.
Notas
- as linhas inseridas pelo cliente em algum formato de dados são empacotadas em um único bloco quando:
- o formato de inserção é baseado em linhas (como CSV, TSV, Values, JSONEachRow etc.) e os dados contêm menos de
max_insert_block_sizelinhas (~1 000 000 por padrão) ou menos demin_chunk_bytes_for_parallel_parsingbytes (10 MB por padrão), caso o parsing paralelo esteja em uso (habilitado por padrão) - o formato de inserção é baseado em colunas (como Native, Parquet, ORC etc.) e os dados contêm apenas um bloco de dados
- o formato de inserção é baseado em linhas (como CSV, TSV, Values, JSONEachRow etc.) e os dados contêm menos de
- o tamanho do bloco inserido, em geral, pode depender de muitas configurações (por exemplo:
max_block_size,max_insert_block_size,min_insert_block_size_rows,min_insert_block_size_bytes,preferred_block_size_bytesetc.) - se o cliente não recebeu uma resposta do servidor, ele não sabe se a transação foi bem-sucedida e pode repeti-la usando as propriedades de inserção exactly-once
- o ClickHouse usa MVCC com isolamento por snapshot internamente para transações concorrentes
- todas as propriedades ACID continuam válidas mesmo em caso de encerramento/falha do servidor
insert_quorumem diferentes AZs oufsyncdeve estar habilitado para garantir inserts duráveis em uma configuração típica- a “consistência” nos termos ACID não cobre a semântica de sistemas distribuídos; veja https://jepsen.io/consistency, que é controlada por diferentes configurações (
select_sequential_consistency) - esta explicação não cobre um novo recurso de transações que permite ter transações completas em várias tabelas, visões materializadas, para múltiplos SELECTs etc. (veja a próxima seção sobre Transactions, Commit, and Rollback)
Transações, Commit e Rollback
Requisitos
- Implante o ClickHouse Keeper ou o ZooKeeper para rastrear transações
- Somente DB atomic (padrão)
- Somente o mecanismo de tabela MergeTree não replicado
- Ative o suporte experimental a transações adicionando esta configuração em
config.d/transactions.xml:
Observações
- Este é um recurso experimental, e é esperado que haja mudanças.
- Se ocorrer uma exceção durante uma transação, você não poderá confirmar a transação. Isso inclui todas as exceções, inclusive exceções
UNKNOWN_FUNCTIONcausadas por erros de digitação. - Transações aninhadas não são compatíveis; finalize a transação atual e inicie uma nova
Configuração
Ative o suporte experimental a transações
/etc/clickhouse-server/config.d/transactions.xml
Configuração básica para um único nó do servidor ClickHouse com o ClickHouse Keeper habilitado
Consulte a documentação de implantação para saber mais sobre como implantar o servidor ClickHouse e um quórum adequado de nós do ClickHouse Keeper. A configuração mostrada aqui é apenas para fins experimentais.
/etc/clickhouse-server/config.d/config.xml
Exemplo
Verifique se as transações experimentais estão habilitadas
BEGIN TRANSACTION ou START TRANSACTION, seguido de um ROLLBACK, para verificar se as transações experimentais estão habilitadas e se o ClickHouse Keeper também está habilitado, já que ele é usado para rastrear transações.
Crie uma tabela para teste
Inicie uma transação e insira uma linha
Você pode consultar a tabela dentro de uma transação e ver que a linha foi inserida, embora a transação ainda não tenha sido confirmada.
Desfaça a transação e consulte a tabela novamente
Conclua uma transação e consulte a tabela novamente
Introspecção de transações
system.transactions, mas observe que não é possível consultar essa
tabela em uma sessão que esteja em uma transação. Abra uma segunda sessão do clickhouse client para consultar essa tabela.