Pular para o conteúdo principal

Níveis de isolamento e conflitos de gravação em Databricks

O nível de isolamento de uma tabela define o grau em que uma transação deve ser isolada das modificações feitas por operações concorrentes. Os conflitos de gravação nos Databricks dependem do nível de isolamento.

Delta Lake oferece garantias de transações ACID entre leituras e gravações. Isso significa que:

  • Vários gravadores em vários clusters podem modificar simultaneamente uma partição de tabela. Os gravadores veem um Snapshot view consistente da tabela e as gravações ocorrem em uma ordem serial.
    • Os leitores continuam a ver um Snapshot view consistente da tabela com a qual o Job Databricks começa, mesmo quando uma tabela é modificada durante um Job.

Consulte O que são garantias ACID em Databricks?

nota

Databricks Use Delta Lake para todas as tabelas por default. Este artigo descreve o comportamento do site Delta Lake em Databricks.

important

As alterações de metadados fazem com que todas as operações de gravação da concorrente falhem. Essas operações incluem alterações no protocolo da tabela, nas propriedades da tabela ou no esquema de dados.

As leituras de transmissão falham quando encontram um commit que altera os metadados da tabela. Se quiser que a transmissão continue, o senhor deve reiniciá-la. Para conhecer os métodos recomendados, consulte Considerações sobre produção para transmissão estruturada.

Veja a seguir exemplos de consultas que alteram os metadados:

SQL
-- Set a table property.
ALTER TABLE table-name SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

-- Enable a feature using a table property and update the table protocol.
ALTER TABLE table_name SET TBLPROPERTIES ('delta.enableDeletionVectors' = true);

-- Drop a table feature.
ALTER TABLE table_name DROP FEATURE deletionVectors;

-- Upgrade to UniForm.
REORG TABLE table_name APPLY (UPGRADE UNIFORM(ICEBERG_COMPAT_VERSION=2));

-- Update the table schema.
ALTER TABLE table_name ADD COLUMNS (col_name STRING);

Conflitos de gravação com simultaneidade em nível de linha

A simultaneidade no nível da linha reduz os conflitos entre as operações de gravação da concorrente, detectando alterações no nível da linha e resolvendo automaticamente os conflitos que ocorrem quando as gravações da concorrente atualizam ou excluem linhas diferentes no mesmo arquivo de dados.

A simultaneidade em nível de linha geralmente está disponível em Databricks Runtime 14.2 e acima. A simultaneidade em nível de linha é suportada pelo site default nas seguintes condições:

  • Tabelas com vetores de exclusão habilitados e sem particionamento.
  • Tabelas com clustering líquido, a menos que o senhor tenha desativado os vetores de exclusão.

As tabelas com partições não oferecem suporte à simultaneidade em nível de linha, mas ainda podem evitar conflitos entre OPTIMIZE e todas as outras operações de gravação quando os vetores de exclusão estão ativados. Consulte Limitações para simultaneidade em nível de linha.

Para outras versões do Databricks Runtime, consulte Comportamento de visualização de simultaneidade em nível de linha (legado).

MERGE INTO O suporte à simultaneidade em nível de linha requer o Photon no Databricks Runtime 14.2. Em Databricks Runtime 14.3 LTS e acima, Photon não é necessário.

A tabela a seguir descreve quais pares de operações de gravação podem entrar em conflito em cada nível de isolamento com a simultaneidade em nível de linha ativada.

nota

As tabelas com colunas de identidade não são compatíveis com transações concorrente. Veja as colunas de identidade de uso em Delta Lake.

INSERIR (1)

UPDATE, DELETE, MERGE INTO

OPTIMIZE

INSERT

Não pode entrar em conflito

UPDATE, DELETE, MERGE INTO

Não pode entrar em conflito em WriteSerializable. Pode entrar em conflito em Serializable ao modificar a mesma linha. Consulte Limitações para simultaneidade em nível de linha.

Pode entrar em conflito ao modificar a mesma linha. Consulte Limitações para simultaneidade em nível de linha.

OPTIMIZE

Não pode entrar em conflito

Pode entrar em conflito quando ZORDER BY é usado. Caso contrário, não pode entrar em conflito.

Pode entrar em conflito quando ZORDER BY é usado. Caso contrário, não pode entrar em conflito.

important

(1) Todas as operações do site INSERT nas tabelas acima descrevem operações de acréscimo que não leem nenhum dado da mesma tabela antes de fazer o commit. INSERT As operações que contêm subconsultas que leem a mesma tabela suportam a mesma simultaneidade que MERGE.

REORG operações têm semântica de isolamento idêntica a OPTIMIZE ao reescrever arquivos de dados para refletir as alterações registradas em vetores de exclusão. Quando o senhor usa o site REORG para aplicar um upgrade, os protocolos da tabela são alterados, o que entra em conflito com todas as operações em andamento.

Conflitos de gravação sem simultaneidade em nível de linha

A tabela a seguir descreve quais pares de operações de gravação podem entrar em conflito em cada nível de isolamento.

As tabelas não oferecem suporte à simultaneidade em nível de linha se tiverem partições definidas ou se os vetores de exclusão não estiverem habilitados. Databricks Runtime 14.2 ou acima é necessário para a simultaneidade em nível de linha.

nota

As tabelas com colunas de identidade não são compatíveis com transações concorrente. Veja as colunas de identidade de uso em Delta Lake.

INSERIR (1)

UPDATE, DELETE, MERGE INTO

OPTIMIZE

INSERT

Não pode entrar em conflito

UPDATE, DELETE, MERGE INTO

Não pode entrar em conflito em WriteSerializable. Pode entrar em conflito em Serializable. Consulte evitar conflitos com partições.

Pode entrar em conflito em Serializable e WriteSerializable. Consulte evitar conflitos com partições.

OPTIMIZE

Não pode entrar em conflito

Não pode entrar em conflito com tabelas com vetores de exclusão habilitados, a menos que ZORDER BY seja usado. Caso contrário, pode entrar em conflito.

Não pode entrar em conflito com tabelas com vetores de exclusão habilitados, a menos que ZORDER BY seja usado. Caso contrário, pode entrar em conflito.

important

(1) Todas as operações do site INSERT nas tabelas acima descrevem operações de acréscimo que não leem nenhum dado da mesma tabela antes de fazer o commit. INSERT As operações que contêm subconsultas que leem a mesma tabela suportam a mesma simultaneidade que MERGE.

REORG operações têm semântica de isolamento idêntica a OPTIMIZE ao reescrever arquivos de dados para refletir as alterações registradas em vetores de exclusão. Quando o senhor usa o site REORG para aplicar um upgrade, os protocolos da tabela são alterados, o que entra em conflito com todas as operações em andamento.

Limitações para simultaneidade em nível de linha

Algumas limitações se aplicam à simultaneidade em nível de linha. Para as operações a seguir, a resolução de conflitos segue a simultaneidade normal para conflitos de gravação em Databricks. Consulte Conflitos de gravação sem simultaneidade em nível de linha.

  • comando com cláusulas condicionais complexas, incluindo as seguintes:

    • Condições em tipos de dados complexos, como estruturas, matrizes ou mapas.
    • Condições usando expressões e subconsultas não determinísticas.
    • Condições que contêm subconsultas correlacionadas.
  • Em Databricks Runtime 14.2, MERGE comando deve usar um predicado explícito na tabela de destino para filtrar as linhas que correspondem à tabela de origem. Para a resolução do site merge, o filtro verifica apenas as linhas que podem entrar em conflito com base nas condições do filtro em operações concorrentes.

nota

A detecção de conflitos em nível de linha pode aumentar o tempo total de execução. No caso de muitas transações concorrente, o escritor prioriza a latência em relação à resolução de conflitos, e podem ocorrer conflitos.

Todas as limitações para vetores de exclusão também se aplicam. Consulte Limitações.

Quando o senhor acessa o site Delta Lake commit sem ler a tabela?

As operações Delta Lake INSERT ou append não leem o estado da tabela antes de fazer o commit se as seguintes condições forem atendidas:

  1. A lógica é expressa usando a lógica INSERT SQL ou o modo append.
  2. A lógica não contém subconsultas ou condicionais que façam referência à tabela visada pelas operações de gravação.

Como em outras confirmações, o site Delta Lake valida e resolve as versões da tabela em commit usando metadados na transação log, mas nenhuma versão da tabela é realmente lida.

nota

Muitos padrões comuns usam as operações do MERGE para inserir dados com base nas condições da tabela. Embora seja possível reescrever essa lógica usando instruções INSERT, se alguma expressão condicional fizer referência a uma coluna na tabela de destino, essas instruções terão as mesmas limitações de simultaneidade de MERGE.

Escreva níveis de isolamento serializáveis versus serializáveis

O nível de isolamento de uma tabela define o grau em que uma transação deve ser isolada das modificações feitas por transações concorrentes. O Delta Lake no Databricks oferece suporte a dois níveis de isolamento: Serializable e WriteSerializable.

  • Serializável : o nível de isolamento mais forte. Ele garante que as operações de gravação confirmadas e todas as leituras sejam serializáveis. As operações são permitidas desde que exista uma sequência em série de execução, uma de cada vez, que gere o mesmo resultado visto na tabela. Para as operações de gravação, a sequência serial é exatamente a mesma que a vista na história da tabela.

  • WriteSerializable (padrão) : Um nível de isolamento mais fraco do que Serializable. Ele garante apenas que as operações de gravação (ou seja, não as leituras) sejam serializáveis. No entanto, isso ainda é mais forte do que o isolamento do Snapshot. WriteSerializable é o nível de isolamento default porque oferece um ótimo equilíbrio entre consistência e disponibilidade de dados para as operações mais comuns.

    Nesse modo, o conteúdo da tabela Delta pode ser diferente do que se espera da sequência de operações vistas no histórico da tabela. Isso ocorre porque esse modo permite que determinados pares de gravações concorrente (digamos, operações X e Y) prossigam de forma que o resultado seja como se Y tivesse sido executado antes de X (ou seja, serializável entre eles), embora a história mostre que Y foi cometido depois de X. Para proibir essa reordenação, defina o nível de isolamento da tabela como Serializável para fazer com que essas transações falhem.

As operações de leitura sempre usam o isolamento do Snapshot. O nível de isolamento de gravação determina se é possível ou não que um leitor veja um Snapshot de uma tabela que, de acordo com o histórico, "nunca existiu".

No nível Serializable, o leitor sempre vê apenas as tabelas que estão em conformidade com o histórico. Para o nível WriteSerializable, um leitor poderia ver uma tabela que não existe no site Delta log.

Por exemplo, considere txn1, uma exclusão de longa duração, e txn2, que insere dados excluídos por txn1. txn2 e txn1 completos e são registrados nessa ordem no histórico. De acordo com o histórico, os dados inseridos em txn2 não deveriam existir na tabela. Para o nível serializável, um leitor nunca veria dados inseridos pelo txn2. No entanto, para o nível WriteSerializable, um leitor pode, em algum momento, ver os dados inseridos pelo txn2.

Para obter mais informações sobre quais tipos de operações podem entrar em conflito entre si em cada nível de isolamento e os possíveis erros, consulte Evitar conflitos usando particionamento e condições de comando disjuntas.

Defina o nível de isolamento

O senhor define o nível de isolamento usando o comando ALTER TABLE.

SQL
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = <level-name>)

onde <level-name> é Serializable ou WriteSerializable.

Por exemplo, para alterar o nível de isolamento do site default WriteSerializable para Serializable, execute:

SQL
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.isolationLevel' = 'Serializable')

Evitar conflitos usando particionamento e condições de comando disjuntas

Em todos os casos marcados como "can conflict" (pode haver conflito), o conflito entre as duas operações depende do fato de elas operarem no mesmo conjunto de arquivos. O senhor pode fazer com que os dois conjuntos de arquivos sejam separados particionando a tabela pelas mesmas colunas usadas nas condições das operações. Por exemplo, os dois comandos UPDATE table WHERE date > '2010-01-01' ... e DELETE table WHERE date < '2010-01-01' entrarão em conflito se a tabela não for particionada por data, pois ambos podem tentar modificar o mesmo conjunto de arquivos. Particionar a tabela por date evitará o conflito. Portanto, o particionamento de uma tabela de acordo com as condições comumente usadas no comando pode reduzir significativamente os conflitos. No entanto, o particionamento de uma tabela por uma coluna com alta cardinalidade pode levar a outros problemas de desempenho devido ao grande número de subdiretórios.

Exceções de conflito

Quando ocorrer um conflito de transação, você observará uma das seguintes exceções:

Exceção simultânea de anexação

Essa exceção ocorre quando uma operação concorrente adiciona arquivos na mesma partição (ou em qualquer lugar em uma tabela não particionada) que sua operação lê. As adições de arquivos podem ser causadas pelas operações INSERT, DELETE, UPDATE, ou MERGE.

Com o default nível de isolamento de,WriteSerializable os arquivos adicionados por INSERT operações cegas (ou seja, operações que anexam dados cegamente sem ler nenhum dado) não entram em conflito com nenhuma operação, mesmo que elas toquem a mesma partição (ou qualquer lugar em uma tabela não particionada). Se o nível de isolamento estiver definido como Serializable, os anexos cegos podem entrar em conflito.

Importante : os apêndices cegos podem entrar em conflito no modo WriteSerializable se várias transações de concorrente que executam operações DELETE, UPDATE ou MERGE puderem fazer referência a valores inseridos por apêndices cegos. Para evitar esse conflito, faça o seguinte:

  • Certifique-se de que as operações concorrente DELETE, UPDATE ou MERGE não leiam os dados anexados.
  • Ter no máximo uma DELETE, UPDATE ou MERGE operações que possam ler os dados anexados.

Essa exceção é frequentemente lançada durante as operações de concorrente DELETE, UPDATE ou MERGE. Embora as operações concorrente possam estar atualizando fisicamente diferentes diretórios de partição, uma delas pode ler a mesma partição que a outra atualiza simultaneamente, causando assim um conflito. O senhor pode evitar isso tornando a separação explícita na condição de operações. Considere o exemplo a seguir.

Scala
// Target 'deltaTable' is partitioned by date and country
deltaTable.as("t").merge(
source.as("s"),
"s.user_id = t.user_id AND s.date = t.date AND s.country = t.country")
.whenMatched().updateAll()
.whenNotMatched().insertAll()
.execute()

Suponha que o senhor execute o código acima simultaneamente para diferentes datas ou países. Como cada Job está trabalhando em uma partição independente na tabela de destino Delta, o senhor não espera nenhum conflito. No entanto, a condição não é suficientemente explícita e pode varrer toda a tabela e entrar em conflito com as operações concorrentes que atualizam outras partições. Em vez disso, o senhor pode reescrever a declaração para adicionar data e país específicos à condição merge, conforme mostrado no exemplo a seguir.

Scala
// Target 'deltaTable' is partitioned by date and country
deltaTable.as("t").merge(
source.as("s"),
"s.user_id = t.user_id AND s.date = t.date AND s.country = t.country AND t.date = '" + <date> + "' AND t.country = '" + <country> + "'")
.whenMatched().updateAll()
.whenNotMatched().insertAll()
.execute()

Essas operações agora são seguras para execução simultânea em diferentes datas e países.

Exceção simultânea de exclusão de leitura

Essa exceção ocorre quando uma concorrente operações excluiu um arquivo que suas operações leram. As causas comuns são as operações DELETE, UPDATE ou MERGE que reescrevem arquivos.

Exceção de exclusão simultânea

Essa exceção ocorre quando uma operação concorrente exclui um arquivo que a sua operação também exclui. Isso pode ser causado por duas operações de compactação concorrente que reescrevem os mesmos arquivos.

Exceção de alteração de metadados

Essa exceção ocorre quando uma transação concorrente atualiza os metadados de uma tabela Delta. As causas comuns são as operações ALTER TABLE ou gravações em sua tabela Delta que atualizam o esquema da tabela.

Exceção de transação simultânea

Se uma consulta de transmissão que usa o mesmo local de ponto de verificação for iniciada várias vezes simultaneamente e tentar gravar na tabela Delta ao mesmo tempo, o senhor poderá ter que fazer isso. O senhor nunca deve fazer com que duas consultas de transmissão usem o mesmo local de ponto de verificação e execução ao mesmo tempo.

Exceção de alteração de protocolo

Essa exceção pode ocorrer nos seguintes casos:

  • Quando sua tabela Delta é atualizada para uma nova versão de protocolo. Para que as operações futuras sejam bem-sucedidas, talvez seja necessário atualizar o Databricks Runtime.
  • Quando vários escritores estão criando ou substituindo uma tabela ao mesmo tempo.
  • Quando vários escritores estão escrevendo em um caminho vazio ao mesmo tempo.

Consulte Como Databricks gerenciar Delta Lake compatibilidade de recursos? para obter mais detalhes.

Comportamento de visualização de simultaneidade em nível de linha (legado)

Esta seção descreve os comportamentos de visualização da simultaneidade no nível da linha em Databricks Runtime 14.1 e abaixo. A simultaneidade em nível de linha sempre exige vetores de exclusão.

Em Databricks Runtime 13.3 LTS e acima, as tabelas com o Liquid clustering ativado habilitam automaticamente a simultaneidade em nível de linha.

Em Databricks Runtime 14.0 e 14.1, o senhor pode ativar a simultaneidade em nível de linha para tabelas com vetores de exclusão definindo a seguinte configuração para o clustering ou SparkSession:

ini
spark.databricks.delta.rowLevelConcurrencyPreview = true

Em Databricks Runtime 14.1 e abaixo, o compute não-Photon suporta apenas a simultaneidade em nível de linha para DELETE operações.