Simultaneidade e consistência de dados

O conteúdo do script nesta página é para navegação apenas e não altera o conteúdo de nenhuma forma.

Este capítulo explica como o Oracle AI Database mantém dados consistentes em um ambiente de banco de dados multiusuário.

Introdução à Simultaneidade e Consistência de Dados

Em um banco de dados de usuário único, um usuário pode modificar dados sem preocupação de outros usuários modificando os mesmos dados ao mesmo tempo. No entanto, em um banco de dados de vários usuários, as instruções em várias transações simultâneas podem atualizar os mesmos dados. Transações executadas simultaneamente devem produzir resultados significativos e consistentes.

Um banco de dados multiusuário deve fornecer o seguinte:

Para descrever o comportamento consistente da transação quando as transações são executadas simultaneamente, os pesquisadores de banco de dados definiram um modelo de isolamento da transação chamado serializability. Uma transação serializável opera em um ambiente que a faz parecer que nenhum outro usuário estava modificando dados no banco de dados.

Embora esse grau de isolamento entre transações seja geralmente desejável, a execução de muitos aplicativos no modo serializável pode comprometer seriamente a taxa de transferência dos aplicativos. O isolamento completo de transações executadas simultaneamente pode significar que uma transação não pode executar uma inserção em uma tabela que está sendo consultada por outra transação. Em suma, as considerações do mundo real geralmente exigem um compromisso entre o isolamento perfeito da transação e o desempenho.

O Oracle AI Database mantém a consistência dos dados usando um modelo de consistência de diversidade e vários tipos de bloqueios e transações. Desta forma, o banco de dados pode apresentar uma view de dados para vários usuários simultâneos, com cada view consistente até um ponto no tempo. Como diferentes versões de blocos de dados podem existir simultaneamente, as transações podem ler a versão dos dados confirmados no momento exigido por uma consulta e retornar resultados consistentes em um único ponto no tempo.

Consistência de Leitura Multiversão

No Oracle AI Database, o multiversionamento é a capacidade de materializar simultaneamente várias versões de dados. O Oracle AI Database mantém a consistência de leitura em várias seções.

As consultas de um banco de dados Oracle têm as seguintes características:

Consistência de Leitura no Nível do Demonstrativo

O Oracle AI Database sempre impõe consistência de leitura no nível da instrução, o que garante que os dados retornados por uma única consulta sejam confirmados e consistentes para um único ponto no tempo.

O momento em que uma única instrução SQL é consistente depende do nível de isolamento da transação e da natureza da consulta:

Consulte Também: Guia de Desenvolvimento do Oracle AI Database para saber mais sobre o Flashback Query

Consistência de Leitura no Nível da Transação

O Oracle AI Database também pode fornecer consistência de leitura para todas as consultas em uma transação, conhecida como consistência de leitura no nível da transação.

Nesse caso, cada instrução em uma transação vê dados do mesmo ponto no tempo. Este é o momento em que a transação começou.

As consultas feitas por uma transação serializável veem as alterações feitas pela própria transação. Por exemplo, uma transação que atualiza employees e, em seguida, consulta employees verá as atualizações. A consistência de leitura no nível da transação produz leituras repetíveis e não expõe uma consulta a leituras fantasmas.

Consistência de Leitura e Segmentos de Desfazer

Para gerenciar o modelo de consistência de leitura multiversão, o banco de dados deve criar um conjunto de dados com consistência de leitura quando uma tabela é consultada e atualizada simultaneamente.

O Oracle AI Database obtém consistência de leitura por meio da desfazer dados.

Sempre que um usuário modifica dados, o Oracle AI Database cria entradas de undo, que ele grava para desfazer segmentos. Os segmentos de undo contêm os valores antigos de dados que foram alterados por transações não submetidas a commit ou a commit recentemente. Assim, várias versões dos mesmos dados, todas em diferentes pontos no tempo, podem existir no banco de dados. O banco de dados pode usar snapshots de dados em diferentes pontos no tempo para fornecer views consistentes em leitura dos dados e ativar consultas sem bloqueio.

A consistência de leitura é garantida em ambientes de instância única e Oracle Real Application Clusters (Oracle RAC). O Oracle RAC usa um mecanismo de transferência de bloco cache-to-cache conhecido como cache fusion para transferir imagens consistentes em leitura de blocos de dados de uma instância de banco de dados para outra.

Consulte Também:

Consistência de Leitura: Exemplo

Este exemplo mostra uma consulta que usa dados de undo para fornecer consistência de leitura no nível da instrução no nível de isolamento de commit de leitura.

Figura 1: Consistência de Leitura no Nível de Isolamento Reservado de Leitura

Descrição da ilustração cncpt069.gif

À medida que o banco de dados recupera blocos de dados em nome de uma consulta, o banco de dados garante que os dados em cada bloco reflitam o conteúdo do bloco quando a consulta começou. O banco de dados faz rollback das alterações no bloco conforme necessário para reconstruí-lo até o momento em que a consulta começou a processar.

O banco de dados usa um mecanismo de ordenação interno chamado SCN para garantir a ordem das transações. À medida que a instrução SELECT entra na fase de execução, o banco de dados determina o SCN registrado no momento em que a consulta começou a ser executada. Na Figura 12-1, este SCN é 10023. A consulta só vê dados confirmados com relação ao SCN 10023.

Na Figura 12-1, os blocos com SCNs após 10023 indicam dados alterados, conforme mostrado pelos dois blocos com SCN 10024. A instrução SELECT requer uma versão do bloco consistente com as alterações submetidas a commit. O banco de dados copia os blocos de dados atuais para um novo buffer e aplica dados de undo para reconstruir versões anteriores dos blocos. Esses blocos de dados reconstruídos são chamados de clones CR (consistent read).

Na Figura 12-1, o banco de dados cria dois clones CR: um bloco consistente para SCN 10006 e o outro bloco consistente para SCN 10021. O banco de dados retorna os dados reconstruídos para a consulta. Dessa forma, o Oracle AI Database impede leituras sujas.

Consulte Também: "Buffer Cache do Banco de Dados" e "Números de Alteração do Sistema (SCNs)"

Ler Consistência e Listas de Transações Interessadas

O cabeçalho do bloco de cada bloco de segmento contém uma lista de transações interessadas (ITL).

O banco de dados usa a ITL para determinar se uma transação foi não confirmada quando o banco de dados começou a modificar o bloco.

As entradas na ITL descrevem quais transações têm linhas bloqueadas e quais linhas no bloco contêm alterações confirmadas e não confirmadas. A ITL aponta para a tabela de transações no segmento de undo, que fornece informações sobre o tempo de alterações no banco de dados.

Em certo sentido, o cabeçalho do bloco contém um histórico recente de transações que afetaram cada linha do bloco. O parâmetro INITRANS das instruções CREATE TABLE e ALTER TABLE controla o valor do histórico de transações que é mantido.

Consulte Também: Referência de Linguagem SQL do Oracle AI Database para saber mais sobre o parâmetro INITRANS

Consistência de Leitura e Inserções Diferidas

Um tipo especial de inserção conhecido como inserção diferida não usa o mecanismo de consistência de leitura padrão.

Uma inserção diferida usa a dica MEMOPTIMIZE_WRITE para inserir em uma tabela especificada como MEMOPTIMIZE FOR WRITE. O banco de dados armazena essas inserções em buffers no pool grande e não no cache de buffer. O banco de dados não rastreia as alterações usando redo e undo. Em vez disso, o banco de dados automaticamente confirma as alterações quando o Coordenador de Gerenciamento de Espaço (SMCO) grava o buffer no disco. Não é possível fazer rollback das alterações.

As inserções diferidas diferem das inserções convencionais de maneiras importantes:

Os aplicativos cliente que devem evitar a perda de dados devem manter uma cópia local dos dados após a gravação no pool grande. O cliente pode usar o pacote DBMS_MEMOPTIMIZE para rastrear a durabilidade das gravações na memória e o pacote DBMS_MEMOPTIMIZE_ADMIN para forçar o banco de dados a gravar no disco.

Consulte Também:

Mecanismos de bloqueio

Em geral, os bancos de dados multiusuários usam alguma forma de bloqueio de dados para resolver os problemas associados à simultaneidade, consistência e integridade dos dados.

Um bloqueio é um mecanismo que impede a interação destrutiva entre transações que acessam o mesmo recurso.

Consulte Também: "Visão Geral do Mecanismo de Bloqueio do Oracle AI Database"

Níveis de Isolamento de Transação ANSI/ISO

O padrão SQL, que foi adotado pelo ANSI e pelo ISO/IEC, define quatro níveis de isolamento de transações. Esses níveis têm diferentes graus de impacto no throughput do processamento de transações.

Esses níveis de isolamento são definidos em termos de fenômenos que devem ser evitados entre transações executadas simultaneamente. Os fenômenos evitáveis são:

O padrão SQL define quatro níveis de isolamento em termos dos fenômenos que uma transação em execução em um nível de isolamento específico pode experimentar. A Tabela 12-1 mostra os níveis.

Tabela 1 Fenômenos de Leitura Evitável por Nível de Isolamento

Nível de Isolamento Leitura Suja Leitura Não Repetível Leitura Fantasma
Leitura não confirmada Possível Possível Possível
Leitura confirmada Não possível Possível Possível
Leitura Repetível Não possível Não possível Possível
Serializável Não possível Não possível Não possível

O Oracle AI Database oferece os níveis de isolamento de leitura confirmada (padrão) e serializável. Além disso, o banco de dados oferece um modo somente leitura.

Consulte Também:

Visão geral dos níveis de isolamento de transações do Oracle AI Database

O padrão ANSI para níveis de isolamento de transação é definido em termos dos fenômenos que são permitidos ou impedidos para cada nível de isolamento.

O Oracle AI Database fornece os níveis de isolamento de transações:

Consulte Também:

Nível de Isolamento de Leitura Confirmada

No nível de isolamento de leitura confirmada, cada consulta executada por uma transação vê apenas os dados confirmados antes da consulta, e não da transação iniciada.

Este nível de isolamento é o padrão. Ele é apropriado para ambientes de banco de dados em que poucas transações provavelmente entrarão em conflito.

Uma consulta em uma transação de leitura confirmada evita a leitura de dados que são confirmados enquanto a consulta está em andamento. Por exemplo, se uma consulta estiver no meio de uma varredura de uma tabela de milhões de linhas e uma transação diferente fizer commit de uma atualização na linha 950.000, a consulta não verá essa alteração quando ler a linha 950.000. No entanto, como o banco de dados não impede que outras transações modifiquem dados lidos por uma consulta, outras transações podem alterar dados entre execuções de consulta. Assim, uma transação que executa a mesma consulta duas vezes pode experimentar leituras difusas e fantasmas.

Consistência de Leitura no Nível de Isolamento Reservado

O banco de dados fornece um conjunto de resultados consistente para cada consulta, garantindo a consistência dos dados, sem nenhuma ação do usuário.

É garantido um conjunto consistente de resultados a uma consulta implícita, como uma consulta implícita por uma cláusula WHERE em uma instrução UPDATE. No entanto, cada instrução em uma consulta implícita não vê as alterações feitas pela própria instrução DML, mas vê os dados como existiam antes de as alterações serem feitas.

Se uma lista SELECT contiver uma função PL/SQL, o banco de dados aplicará consistência de leitura no nível da instrução para execução de SQL no código de função PL/SQL, em vez de no nível SQL pai. Por exemplo, uma função pode acessar uma tabela cujos dados são alterados e confirmados por outro usuário. Para cada execução do SELECT na função, um novo snapshot com consistência de leitura é estabelecido.

Consulte Também: "Subconsultas"

Gravações Conflitantes em Transações Confirmadas de Leitura

Em uma transação de leitura confirmada, uma gravação conflitante ocorre quando a transação tenta alterar uma linha atualizada por uma transação concorrente não confirmada.

A transação que impede a modificação da linha às vezes é chamada de transação de bloqueio. A transação de leitura confirmada aguarda que a transação de bloqueio termine e libere seu bloqueio de linha.

As opções são as seguintes:

A tabela a seguir mostra como a transação 1, que pode ser serializável ou confirmada por leitura, interage com a transação confirmada por leitura 2. Ela mostra uma situação clássica conhecida como atualização perdida. A atualização feita pela transação 1 não está na tabela mesmo que a transação 1 tenha sido confirmada. A elaboração de uma estratégia para lidar com atualizações perdidas é uma parte importante do desenvolvimento de aplicativos.

Tabela 2 Gravações Conflitantes e Atualizações Perdidas em uma Transação COMPROMETIDA DE LEITURA

Sessão 1 Sessão 2 Explicação
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
  ('Banda', 'Greene',
 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6200
 Greene 9500 
Nenhuma ação. A Sessão 1 consulta os salários de Banda, Greene e Hintz. Nenhum funcionário chamado Hintz foi encontrado.
SQL> UPDATE employees
  SET salary = 7000 WHERE
  last_name = 'Banda';
Nenhuma ação. A Sessão 1 inicia uma transação atualizando o salário de Banda. O nível de isolamento padrão para a transação 1 é READ COMMITTED.
Nenhuma ação.
SQL> SET TRANSACTION
  ISOLATION LEVEL
  READ COMMITTED;
A sessão 2 inicia a transação 2 e define o nível de isolamento explicitamente como READ COMMITTED.
Nenhuma ação.
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
 ('Banda', 'Greene',
 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6200
 Greene 9500
A Transação 2 consulta os salários de Banda, Greene e Hintz. O Oracle AI Database usa consistência de leitura para mostrar o salário da Banda antes da atualização não confirmada feita pela transação 1.
Nenhuma ação.
SQL> UPDATE employees
  SET salary = 9900
  WHERE last_name='Greene';
A transação 2 atualiza o salário de Greene com sucesso porque a transação 1 bloqueou apenas a linha Banda.
SQL> INSERT INTO
  employees (employee_id,
  last_name, email,
  hire_date, job_id)
  VALUES (210, 'Hintz',
  'JHINTZ', SYSDATE,
  'SH_CLERK');
Nenhuma ação. A Transação 1 insere uma linha para o funcionário Hintz, mas não efetua commit.
Nenhuma ação.
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
  ('Banda', 'Greene',
 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6200
 Greene 9900

A Transação 2 consulta os salários dos funcionários Banda, Greene e Hintz.

A Transação 2 vê sua própria atualização no salário de Greene. A Transação 2 não vê a atualização não confirmada para o salário de Banda ou a inserção de Hintz feita pela transação 1.

Nenhuma ação.
SQL> UPDATE employees SET
 salary = 6300 WHERE
  last_name = 'Banda';

  -- prompt does not return 
A Transação 2 tenta atualizar a linha do Banda, que está atualmente bloqueada pela transação 1, criando uma gravação conflitante. A transação 2 aguarda até o término da transação 1.
SQL> COMMIT;
Nenhuma ação. A Transação 1 confirma seu trabalho, encerrando a transação.
Nenhuma ação.
1 row updated.

  SQL>
O bloqueio na linha Banda foi liberado, então a transação 2 continua com sua atualização para o salário de Banda.
Nenhuma ação.
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
 ('Banda', 'Greene',
  'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6300
 Greene 9900
 Hintz
A Transação 2 consulta os salários dos funcionários Banda, Greene e Hintz. A inserção de Hintz confirmada pela transação 1 agora está visível para a transação 2. A Transação 2 vê sua própria atualização para o salário de Banda.
Nenhuma ação.
COMMIT;
A Transação 2 confirma seu trabalho, encerrando a transação.
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
  ('Banda', 'Greene',
 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6300
 Greene 9900
 Hintz
Nenhuma ação. A Sessão 1 consulta as linhas de Banda, Greene e Hintz. O salário de Banda é 6300, que é a atualização feita pela transação 2. A atualização do salário de Banda para 7000 feita pela transação 1 está agora "perdida".

Consulte Também:

Nível de isolamento serializável

No nível de isolamento serializável, uma transação só vê as alterações confirmadas no momento em que a transação, e não a consulta, começou e as alterações feitas pela própria transação.

Uma transação serializável opera em um ambiente que a faz parecer que nenhum outro usuário estava modificando dados no banco de dados. O isolamento serializável é adequado para ambientes:

Em isolamento serializável, a consistência de leitura normalmente obtida no nível da instrução se estende a toda a transação. Qualquer linha lida pela transação é assegurada de ser a mesma quando lida novamente. Qualquer consulta é garantida para retornar os mesmos resultados durante a transação, portanto, as alterações feitas por outras transações não são visíveis para a consulta, independentemente de quanto tempo ela esteja em execução. Transações serializáveis não experimentam leituras sujas, leituras difusas ou leituras fantasmas.

O Oracle AI Database permite que uma transação serializável modifique uma linha somente se as alterações feitas na linha por outras transações já tiverem sido confirmadas quando a transação serializável começou. O banco de dados gera um erro quando uma transação serializável tenta atualizar ou excluir dados alterados por outra transação que foi confirmada após o início da transação serializável:

ORA-08177: Cannot serialize access for this transaction

Quando uma transação serializável falha com o erro ORA-08177, um aplicativo pode executar várias ações, incluindo as seguintes:

A tabela a seguir mostra como uma transação serializável interage com outras transações. Se a transação serializável não tentar alterar uma linha confirmada por outra transação após o início da transação serializável, um problema de acesso serializado será evitado.

Tabela 3 - Transação serializável

Sessão 1 Sessão 2 Explicação
SQL> SELECT last_name, salary FROM employees WHERE
  last_name IN ('Banda',
  'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 6200
 Greene 9500
Nenhuma ação. A Sessão 1 consulta os salários de Banda, Greene e Hintz. Nenhum funcionário chamado Hintz foi encontrado.
SQL> UPDATE employees
  SET salary = 7000
  WHERE last_name='Banda';
Nenhuma ação. A Sessão 1 inicia a transação 1 atualizando o salário de Banda. O nível de isolamento padrão é READ COMMITTED.
Nenhuma ação.
SQL> SET TRANSACTION
  ISOLATION LEVEL SERIALIZABLE;
A Sessão 2 inicia a transação 2 e a define no nível de isolamento SERIALIZABLE.
Nenhuma ação.
SQL> SELECT last_name, salary FROM employees
  WHERE last_name IN
  ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------ ----------
 Banda 6200
 Greene 9500
A Transação 2 consulta os salários de Banda, Greene e Hintz. O Oracle AI Database usa consistência de leitura para mostrar o salário da Banda antes da atualização não confirmada feita pela transação 1.
Nenhuma ação.
SQL> UPDATE employees
  SET salary = 9900
  WHERE last_name = 'Greene';
A Transação 2 atualiza o salário Greene com sucesso porque somente a linha Banda está bloqueada.
SQL> INSERT INTO employees
  (employee_id, last_name,
  email, hire_date, job_id)
  VALUES (210, 'Hintz',
  'JHINTZ', SYSDATE,'SH_CLERK');
Nenhuma ação. A Transação 1 insere uma linha para o funcionário Hintz.
SQL> COMMIT;
Nenhuma ação. A Transação 1 confirma seu trabalho, encerrando a transação.
SQL> SELECT last_name, salary
  FROM employees
  WHERE last_name IN
  ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 7000
 Greene 9500
 Hintz
SQL> SELECT last_name, salary FROM employees
  WHERE last_name IN
 ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ---------
 Banda 6200
 Greene 9900

A Sessão 1 consulta os salários dos funcionários Banda, Greene e Hintz e vê as alterações confirmadas pela transação 1. A sessão 1 não vê a atualização não confirmada de Greene feita pela transação 2.

A Transação 2 consulta os salários dos funcionários Banda, Greene e Hintz. A consistência de leitura do Oracle AI Database garante que a inserção de Hintz e a atualização do Banda confirmadas pela transação 1 não estejam visíveis para a transação 2. A Transação 2 vê sua própria atualização do salário de Greene.

Nenhuma ação.
COMMIT;
A Transação 2 confirma seu trabalho, encerrando a transação.
SQL> SELECT last_name, salary
  FROM employees
  WHERE last_name IN
  ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 7000
 Greene 9900
 Hintz
SQL> SELECT last_name, salary
 FROM employees
  WHERE last_name IN
  ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ---------
 Banda 7000
 Greene 9900
 Hintz
Ambas as sessões consultam os salários de Banda, Greene e Hintz. Cada sessão vê todas as alterações confirmadas feitas pela transação 1 e pela transação 2.
SQL> UPDATE employees
  SET salary = 7100
  WHERE last_name = 'Hintz';
Nenhuma ação. A Sessão 1 inicia a transação 3 atualizando o salário de Hintz. O nível de isolamento padrão para a transação 3 é READ COMMITTED.
Nenhuma ação.
SQL> SET TRANSACTION
  ISOLATION LEVEL SERIALIZABLE;
A Sessão 2 inicia a transação 4 e a define no nível de isolamento SERIALIZABLE.
Nenhuma ação.
SQL> UPDATE employees
  SET salary = 7200
  WHERE last_name = 'Hintz';

  -- prompt does not return
A transação 4 tenta atualizar o salário de Hintz, mas é bloqueada porque a transação 3 bloqueou a linha Hintz. As filas da transação 4 atrás da transação 3.
SQL> COMMIT;
Nenhuma ação. A Transação 3 confirma sua atualização do salário de Hintz, encerrando a transação.
Nenhuma ação.
UPDATE employees
  SET salary = 7200
  WHERE last_name = 'Hintz'
 *
 ERROR at line 1:
  ORA-08177: can't
  serialize access for
  this transaction
O commit que encerra a transação 3 faz com que a atualização de Hintz na transação 4 falhe com o erro ORA-08177. O erro de problema ocorre porque a transação 3 confirmou a atualização de Hintz após o início da transação 4.
Nenhuma ação.
SQL> ROLLBACK;
A Sessão 2 faz rollback da transação 4, que encerra a transação.
Nenhuma ação.
SQL> SET TRANSACTION
  ISOLATION LEVEL SERIALIZABLE;
A sessão 2 inicia a transação 5 e a define no nível de isolamento SERIALIZABLE.
Nenhuma ação.
SQL> SELECT last_name,
  salary FROM employees
  WHERE last_name IN
  ('Banda', 'Greene', 'Hintz');

  LAST_NAME SALARY
 ------------- ----------
 Banda 7000
 Greene 9900
 Hintz 7100
A Transação 5 consulta os salários de Banda, Greene e Hintz. A atualização de salário de Hintz confirmada pela transação 3 está visível.
Nenhuma ação.
SQL> UPDATE employees
  SET salary = 7200
  WHERE last_name='Hintz';

  1 row updated.

A Transação 5 atualiza o salário de Hintz para um valor diferente. Como a atualização de Hintz feita pela transação 3 foi confirmada antes do início da transação 5, o problema de acesso serializado é evitado.

Observação: Se uma transação diferente atualizar e confirmar a linha Hintz após o início da transação 5, o problema de acesso serializado ocorrerá novamente.

Nenhuma ação.
SQL> COMMIT; 
A sessão 2 confirma a atualização sem problemas, encerrando a transação.

Consulte Também:

Nível de Isolamento Somente Leitura

O nível de isolamento somente leitura é semelhante ao nível de isolamento serializável, mas as transações somente leitura não permitem que os dados sejam modificados na transação, a menos que o usuário seja SYS.

As transações somente leitura não são suscetíveis ao erro ORA-08177. Transações somente leitura são úteis para gerar relatórios nos quais o conteúdo deve ser consistente com relação ao horário em que a transação começou.

O Oracle AI Database obtém consistência de leitura reconstruindo dados conforme necessário nos segmentos de undo. Como os segmentos de undo são usados em uma forma circular, o banco de dados pode substituir dados de undo. Os relatórios de execução longa correm o risco de que os dados de undo necessários para consistência de leitura possam ter sido reutilizados por outra transação, gerando um erro snapshot too old. A definição de um período de retenção de undo, que é o tempo mínimo durante o qual o banco de dados tenta reter dados de undo antigos antes de substituí-los, evita adequadamente esse problema.

Consulte Também:

Visão Geral do Mecanismo de Bloqueio do Oracle AI Database

Um bloqueio é um mecanismo que impede interações destrutivas.

As interações são destrutivas quando atualizam dados incorretamente ou alteram incorretamente estruturas de dados subjacentes, entre transações que acessam dados compartilhados. Os bloqueios desempenham um papel crucial na manutenção da simultaneidade e da consistência do banco de dados.

Resumo do Comportamento de Bloqueio

O banco de dados mantém vários tipos diferentes de bloqueios, dependendo da operação que adquiriu o bloqueio.

Em geral, o banco de dados usa dois tipos de bloqueios: bloqueios exclusivos e bloqueios compartilhados. Apenas um bloqueio exclusivo pode ser obtido em um recurso, como uma linha ou uma tabela, mas muitos bloqueios de compartilhamento podem ser obtidos em um único recurso.

Bloqueios afetam a interação de leitores e escritores. Um leitor é uma consulta de um recurso, enquanto um gravador é uma instrução que modifica um recurso. As seguintes regras resumem o comportamento de bloqueio do Oracle AI Database para leitores e gravadores:

Consulte Também:

Uso de bloqueios

Em um banco de dados de usuário único, os bloqueios não são necessários porque somente um usuário está modificando as informações. Entretanto, quando vários usuários estão acessando e modificando dados, o banco de dados deve fornecer uma maneira de impedir a modificação simultânea dos mesmos dados.

Os bloqueios atendem aos seguintes requisitos importantes do banco de dados:

O Oracle AI Database fornece simultaneidade, consistência e integridade de dados entre as transações por meio de seus mecanismos de bloqueio. O bloqueio ocorre automaticamente e não requer ação do usuário.

A necessidade de bloqueios pode ser ilustrada por uma atualização simultânea de uma única linha. No exemplo a seguir, um aplicativo simples baseado na Web apresenta ao usuário final um e-mail e número de telefone do funcionário. O aplicativo usa uma instrução UPDATE, como a seguinte, para modificar os dados:

UPDATE employees
SET    email = ?, phone_number = ?
WHERE  employee_id = ?
AND    email = ?
AND    phone_number = ?

Na instrução UPDATE anterior, os valores de e-mail e número de telefone na cláusula WHERE são os valores originais não modificados para o funcionário especificado. Esta atualização garante que a linha que o aplicativo modifica não foi alterada após a última leitura do aplicativo e exibida para o usuário. Desta forma, o aplicativo evita o problema de atualização perdida em que um usuário substitui as alterações feitas por outro usuário, perdendo efetivamente a atualização pelo segundo usuário (a Tabela 12-2 mostra um exemplo de atualização perdida). A Tabela 12-4 mostra a sequência de eventos quando duas sessões tentam modificar a mesma linha na tabela employees aproximadamente ao mesmo tempo.

Exemplo de Bloqueio de Linha da Tabela 4

T Sessão 1 Sessão 2 Descrição
t0
SELECT employee_id as ID,
  email, phone_number
  FROM hr.employees
  WHERE last_name='Himuro';
ID EMAIL PHONE_NUMBER
 --- ------- ------------
 118 GHIMURO 515.127.4565
  Na sessão 1, o usuário do hr1 consulta hr.employees para o registro Himuro e exibe os atributos employee_id (118), e-mail (GHIMURO) e número de telefone (515.127.4565).
t1  
SELECT employee_id as ID,
 email, phone_number
  FROM hr.employees
  WHERE last_name='Himuro';
ID EMAIL PHONE_NUMBER
 --- ------- ------------
 118 GHIMURO 515.127.4565
Na sessão 2, o usuário do hr2 consulta hr.employees para o registro Himuro e exibe os atributos employee_id (118), e-mail (GHIMURO) e número de telefone (515.127.4565).
t2
UPDATE hr.employees SET
  phone_number='515.555.1234'
 WHERE employee_id=118
 AND email='GHIMURO'
 AND phone_number =
  '515.127.4565';

  1 row updated.
  Na sessão 1, o usuário hr1 atualiza o número de telefone na linha para 515.555.1234, que adquire um bloqueio na linha GHIMURO.
t3  
UPDATE hr.employees SET
  phone_number='515.555.1235'
 WHERE employee_id=118
 AND email='GHIMURO'
 AND phone_number =
  '515.127.4565';

  -- SQL*Plus does not show
 -- a row updated message or
 -- return the prompt.

Na sessão 2, o usuário hr2 tenta atualizar a mesma linha, mas é bloqueado porque hr1 está processando a linha no momento.

A tentativa de atualização por hr2 ocorre quase simultaneamente com a atualização hr1.

t4
COMMIT;

  Commit complete.
 

Na sessão 1, o usuário hr1 faz commit da transação.

O compromisso torna a mudança para Himuro permanente e desbloqueia a sessão 2, que tem estado à espera.

t5  
0 rows updated.

Na sessão 2, o usuário hr2 descobre que a linha GHIMURO foi modificada de forma que não corresponda mais ao seu predicado.

Como os predicados não correspondem, a sessão 2 não atualiza registros.

t6
UPDATE hr.employees SET
  phone_number='515.555.1235'
 WHERE employee_id=118
 AND email='GHIMURO' AND
  phone_number='515.555.1234';

  1 row updated.
  Na sessão 1, o usuário do hr1 percebe que ele atualizou a linha GHIMURO com o número de telefone errado. O usuário inicia uma nova transação e atualiza o número de telefone na linha para 515.555.1235, que bloqueia a linha GHIMURO.
t7  
SELECT employee_id as ID,
  email, phone_number
  FROM hr.employees
  WHERE last_name='Himuro';
ID EMAIL PHONE_NUMBER
 --- ------- ------------
 118 GHIMURO 515.555.1234
Na sessão 2, o usuário do hr2 consulta hr.employees para o registro Himuro. O registro mostra a atualização do número de telefone confirmada pela sessão 1 em t4. A consistência de leitura do Oracle AI Database garante que a sessão 2 não veja a alteração não confirmada feita em t6.
t8  
UPDATE hr.employees SET
  phone_number='515.555.1235
  WHERE employee_id=118
 AND email='GHIMURO'
 AND phone_number =
 '515.555.1234';

  -- SQL*Plus does not show
 -- a row updated message or
 -- return the prompt.
Na sessão 2, o usuário hr2 tenta atualizar a mesma linha, mas é bloqueado porque hr1 está processando a linha no momento.
t9
ROLLBACK;

  Rollback complete.
  Na sessão 1, o usuário hr1 faz rollback da transação, que a encerra.
t10  
1 row updated.
Na sessão 2, a atualização do número de telefone é bem-sucedida porque a atualização da sessão 1 foi revertida. A linha GHIMURO corresponde ao seu predicado; portanto, a atualização é bem-sucedida.
t11  
COMMIT;

  Commit complete.
A sessão 2 confirma a atualização, encerrando a transação.

O Oracle AI Database obtém automaticamente os bloqueios necessários ao executar instruções SQL. Por exemplo, antes que o banco de dados permita que uma sessão modifique os dados, a sessão deve primeiro bloquear os dados. O bloqueio dá à sessão controle exclusivo sobre os dados para que nenhuma outra transação possa modificar os dados bloqueados até que o bloqueio seja liberado.

Como os mecanismos de bloqueio do Oracle AI Database estão intimamente ligados ao controle de transações, os designers de aplicativos só precisam definir as transações corretamente, e o Oracle AI Database gerencia automaticamente o bloqueio. Os usuários nunca precisam bloquear qualquer recurso explicitamente, embora o Oracle AI Database também permita que os usuários bloqueiem dados manualmente.

As seções a seguir explicam conceitos importantes para entender como o Oracle AI Database alcança a simultaneidade de dados.

Consulte Também: Referência de Tipos e Pacotes PL/SQL do Oracle AI Database para saber mais sobre o pacote OWA_OPT_LOCK, que contém subprogramas que podem ajudar a evitar atualizações perdidas

Modos de bloqueio

O Oracle AI Database usa automaticamente o menor nível aplicável de restritividade para oferecer o maior grau de simultaneidade de dados, mas também oferece integridade de dados segura para falhas.

Quanto menos restritivo for o nível, mais disponíveis serão os dados para acesso de outros usuários. Por outro lado, quanto mais restritivo for o nível, mais limitadas serão as outras transações nos tipos de fechaduras que podem adquirir.

O Oracle AI Database usa dois modos de bloqueio em um banco de dados multiusuário:

Suponha que uma transação use uma instrução SELECT ... FOR UPDATE para selecionar uma única linha de tabela. A transação adquire um bloqueio de linha exclusivo e um bloqueio de tabela de compartilhamento de linhas. O bloqueio de linha permite que outras sessões modifiquem qualquer linha que não seja a linha bloqueada, enquanto o bloqueio de tabela impede que as sessões alterem a estrutura da tabela. Dessa forma, o banco de dados permite a execução do máximo de instruções possível.

Bloquear Conversão e Escalação

O Oracle AI Database executa a conversão de bloqueio conforme necessário.

Na conversão de bloqueio, o banco de dados converte automaticamente um bloqueio de tabela de menor restritividade para um de maior restritividade. Por exemplo, suponha que uma transação emita um SELECT ... FOR UPDATE para um funcionário e, posteriormente, atualiza a linha bloqueada. Nesse caso, o banco de dados converte automaticamente o bloqueio de tabela de compartilhamento de linhas em um bloqueio de tabela exclusivo de linhas. Uma transação contém bloqueios de linha exclusivos para todas as linhas inseridas, atualizadas ou excluídas dentro da transação. Como os bloqueios de linha são adquiridos com o maior grau de restrição, nenhuma conversão de bloqueio é necessária ou executada.

A conversão de bloqueio é diferente da escalação de bloqueio, que ocorre quando vários bloqueios são mantidos em um nível de granularidade (por exemplo, linhas) e um banco de dados eleva os bloqueios para um nível mais alto de granularidade (por exemplo, tabela). Se uma sessão bloquear muitas linhas em uma tabela, alguns bancos de dados escalarão automaticamente os bloqueios de linha para uma única tabela. O número de bloqueios diminui, mas a restrição do que está bloqueado aumenta.

O Oracle AI Database nunca escala bloqueios. A escalada de bloqueio aumenta muito a probabilidade de deadlocks. Suponha que um sistema esteja tentando escalar bloqueios em nome da transação 1, mas não pode devido aos bloqueios mantidos pela transação 2. Um deadlock será criado se a transação 2 também exigir a escalação de bloqueio dos mesmos dados para que possa continuar.

Duração do Bloqueio

O Oracle AI Database libera automaticamente um bloqueio quando algum evento ocorre para que a transação não exija mais o recurso.

Em geral, o banco de dados armazena bloqueios adquiridos por instruções em uma transação durante esse período. Esses bloqueios impedem interferência destrutiva, como leituras sujas, atualizações perdidas e DDL destrutivas de transações simultâneas. Observação: Um bloqueio de tabela obtido em uma tabela filho por causa de uma chave estrangeira não indexada é mantido pela duração do demonstrativo, não pela transação. Além disso, o pacote DBMS_LOCK permite que bloqueios definidos pelo usuário sejam liberados e alocados à vontade e até mesmo mantidos acima dos limites da transação.

O Oracle AI Database libera todos os bloqueios adquiridos pelas instruções em uma transação quando faz commit ou rollback. O Oracle AI Database também libera bloqueios adquiridos após um ponto de salvamento ao fazer rollback para o ponto de salvamento. No entanto, somente as transações que não estiverem aguardando os recursos bloqueados anteriormente poderão adquirir bloqueios nos recursos agora disponíveis. As transações de espera continuam a aguardar até que a transação original seja confirmada ou revertida completamente.

Consulte Também:

Bloqueios e Deadlocks

Um desbloqueio é uma situação em que dois ou mais usuários estão aguardando dados bloqueados uns pelos outros. Os deadlocks impedem que algumas transações continuem a funcionar.

O Oracle AI Database detecta automaticamente deadlocks e os resolve fazendo rollback de uma instrução envolvida no deadlock, liberando um conjunto de bloqueios de linha conflitantes. O banco de dados retorna uma mensagem correspondente à transação que sofre backback no nível da instrução. O rollback da instrução pertence à transação que detecta o deadlock. Em geral, a transação sinalizada deve ser submetida a rollback explicitamente, mas ela pode repetir a instrução rollback depois de aguardar. A Tabela 12-5 ilustra duas transações em um deadlock.

Tabela 5 Transações com Deadlock

T Sessão 1 Sessão 2 Explicação
t0
SQL> UPDATE employees
  SET salary = salary*1.1
 WHERE employee_id = 100;

  1 row updated.
SQL> UPDATE employees
 SET salary = salary*1.1
 WHERE employee_id = 200;

  1 row updated.
A Sessão 1 inicia a transação 1 e atualiza o salário do funcionário 100. A Sessão 2 inicia a transação 2 e atualiza o salário do funcionário 200. Não existe problema porque cada transação bloqueia apenas a linha que tenta atualizar.
t1
SQL> UPDATE employees
  SET salary = salary*1.1
 WHERE employee_id = 200;

  -- prompt does not return
SQL> UPDATE employees
 SET salary = salary*1.1
 WHERE employee_id = 100;

  -- prompt does not return

A Transação 1 tenta atualizar a linha do funcionário 200, que está bloqueada atualmente pela transação 2. A Transação 2 tenta atualizar a linha do funcionário 100, que está atualmente bloqueada pela transação 1.

Um deadlock resulta porque nenhuma transação pode obter o recurso que precisa para prosseguir ou encerrar. Não importa quanto tempo cada transação espere, os bloqueios conflitantes são mantidos.

t2
UPDATE employees
 *
 ERROR at line 1:
 ORA-00060: deadlock detected
 while waiting for resource

  SQL>
 

A transação 1 sinaliza o deadlock e faz rollback da instrução UPDATE emitida em t1. No entanto, a atualização feita em t0 não é submetida a rollback. O prompt é retornado na sessão 1.

Observação: Somente uma sessão no deadlock obtém o erro deadlock, mas qualquer uma delas pode obter o erro.

t3
SQL> COMMIT;

  Commit complete.
  A Sessão 1 confirma a atualização feita em t0, encerrando a transação 1. A tentativa de atualização malsucedida em t1 não foi confirmada.
t4  
1 row updated.

  SQL>
A atualização em t1 na transação 2, que estava sendo bloqueada pela transação 1, é executada. O prompt é retornado.
t5  
SQL> COMMIT;

  Commit complete.
A Sessão 2 confirma as atualizações feitas em t0 e t1, que encerra a transação 2.

Os deadlocks ocorrem com mais frequência quando as transações substituem explicitamente o bloqueio padrão do Oracle AI Database. Como o Oracle AI Database não escalona bloqueios e não usa bloqueios de leitura para consultas, mas usa bloqueios no nível da linha (em vez de no nível da página), os bloqueios ocorrem com pouca frequência.

Consulte Também:

Visão geral de Bloqueios automáticos

O Oracle AI Database bloqueia automaticamente um recurso em nome de uma transação para impedir que outras transações façam algo que exija acesso exclusivo ao mesmo recurso.

O banco de dados adquire automaticamente diferentes tipos de bloqueios em diferentes níveis de restrição, dependendo do recurso e da operação que está sendo executada. Observação: O banco de dados nunca bloqueia linhas ao executar leituras simples.

Os bloqueios do Oracle AI Database são divididos nas categorias mostradas na tabela a seguir.

Categorias de Bloqueio da Tabela 6

Bloquear Descrição Para Saber Mais
Bloqueios DML Proteger dados. Por exemplo, os bloqueios de tabela bloqueiam tabelas inteiras, enquanto os bloqueios de linha bloqueiam as linhas selecionadas. "Bloques DML"
Bloqueios DDL Proteja a estrutura de objetos de esquema - por exemplo, as definições de dicionário de tabelas e views. "Bloques DDL"
Bloqueios do sistema Proteja estruturas internas de banco de dados, como arquivos de dados. Travas, mutexes e bloqueios internos são totalmente automáticos. "Bloques do Sistema"

Bloqueios DML

Um bloqueio DML, também chamado de bloqueio de dados, garante a integridade dos dados acessados simultaneamente por vários usuários.

Por exemplo, um bloqueio DML impede que dois clientes comprem a última cópia de um livro disponível em um livreiro on-line. Os bloqueios DML impedem a interferência destrutiva de operações DML ou DDL simultâneas em conflito.

As instruções DML adquirem automaticamente os seguintes tipos de bloqueios:

Nas seções a seguir, o acrônimo entre parênteses após cada tipo de bloqueio ou modo de bloqueio é a abreviação usada no Monitor de Bloqueios do Oracle Enterprise Manager (Enterprise Manager). O Enterprise Manager pode exibir TM para qualquer bloqueio de tabela, em vez de indicar o modo de bloqueio de tabela (como RS ou SRX).

Bloqueios de linha (TX)

Um bloqueio de linha, também chamado de bloqueio TX, é um bloqueio em uma única linha da tabela. Uma transação adquire um bloqueio de linha para cada linha modificada por uma instrução INSERT, UPDATE, DELETE, MERGE ou SELECT ... FOR UPDATE. O bloqueio de linha existe até que a transação seja confirmada ou revertida.

Os bloqueios de linha servem principalmente como um mecanismo de enfileiramento para impedir que duas transações modifiquem a mesma linha. O banco de dados sempre bloqueia uma linha modificada no modo exclusivo para que outras transações não possam modificar a linha até que a transação que contém o bloqueio seja confirmada ou revertida. O bloqueio de linha fornece o melhor bloqueio de grãos possível e, portanto, fornece a melhor simultaneidade e taxa de transferência possíveis.

Observação: Se uma transação for encerrada devido a uma falha na instância do banco de dados, a recuperação em nível de bloco disponibilizará uma linha antes de toda a transação ser recuperada.

Se uma transação obtiver um bloqueio para uma linha, a transação também adquirirá um bloqueio para a tabela que contém a linha. O bloqueio de tabela impede operações DDL conflitantes que substituiriam as alterações de dados em uma transação atual. A Figura 12-2 ilustra uma atualização da terceira linha em uma tabela. O Oracle AI Database coloca automaticamente um bloqueio exclusivo na linha atualizada e um bloqueio subexclusivo na tabela.

Figura 2: Bloqueios de Linha e Tabela

Descrição da ilustração cncpt265.gif

Bloqueios de linha e simultaneidade

Este cenário ilustra como o Oracle AI Database usa bloqueios de linhas para simultaneidade.

Três sessões consultam as mesmas linhas simultaneamente. As sessões 1 e 2 continuam a fazer atualizações não confirmadas em linhas diferentes, enquanto a sessão 3 não faz atualizações. Cada sessão vê suas próprias atualizações não confirmadas, mas não as atualizações não confirmadas de qualquer outra sessão.

Exemplo de simultaneidade de dados da tabela 7

T Sessão 1 Sessão 2 Sessão 3 Explicação
t0
SELECT employee_id,
 salary
 FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
SELECT employee_id,
 salary
  FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
SELECT employee_id,
  salary
  FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
Três sessões diferentes consultam simultaneamente o ID e o salário dos funcionários 100 e 101. Os resultados retornados por cada consulta são idênticos.
t1
UPDATE hr.employees
 SET salary =
  salary+100
 WHERE
  employee_id=100;
    A Sessão 1 atualiza o salário do funcionário 100, mas não efetua commit. Na atualização, o gravador adquire um bloqueio de nível de linha apenas para a linha atualizada, evitando que outros gravadores modifiquem essa linha.
t2
SELECT employee_id,
 salary
  FROM employees
  WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 612
 101 600
SELECT employee_id,
 salary
 FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
SELECT employee_id,
  salary
  FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
Cada sessão emite simultaneamente a consulta original. A Sessão 1 mostra o salário de 612 resultante da atualização t1. Os leitores das sessões 2 e 3 retornam linhas imediatamente e não aguardam que a sessão 1 encerre sua transação. O banco de dados usa a consistência de leitura de várias seções para mostrar o salário como ele existia antes da atualização na sessão 1.
t3  
UPDATE hr.employee
 SET salary =
 salary+100
 WHERE
  employee_id=101;
  A Sessão 2 atualiza o salário do funcionário 101, mas não efetua o commit da transação. Na atualização, o gravador adquire um bloqueio de nível de linha apenas para a linha atualizada, evitando que outros gravadores modifiquem essa linha.
t4
SELECT employee_id,
 salary
  FROM employees
  WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 612
 101 600
SELECT employee_id,
 salary
 FROM employees
  WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 700
SELECT employee_id,
  salary
  FROM employees
 WHERE employee_id
 IN ( 100, 101 );
EMPLOYEE_ID SALARY
 ----------- ------
 100 512
 101 600
Cada sessão emite simultaneamente a consulta original. A Sessão 1 mostra o salário de 612 resultante da atualização t1, mas não a atualização de salário para o funcionário 101 feita na sessão 2. O leitor na sessão 2 mostra a atualização de salário feita na sessão 2, mas não a atualização de salário feita na sessão 1. O leitor na sessão 3 usa a consistência de leitura para mostrar os salários antes da modificação feita pelas sessões 1 e 2.

Consulte Também:

Armazenamento de Bloqueios de Linha

Diferentemente de alguns bancos de dados, que usam um gerenciador de bloqueios para manter uma lista de bloqueios na memória, o Oracle AI Database armazena informações de bloqueio no bloco de dados que contém a linha bloqueada.

O banco de dados usa um mecanismo de enfileiramento para aquisição de bloqueios de linha. Se uma transação exigir um bloqueio para uma linha desbloqueada, a transação colocará um bloqueio no bloco de dados. Cada linha modificada por essa transação aponta para uma cópia do ID da transação armazenada no cabeçalho do bloco.

Quando uma transação termina, o ID da transação permanece no cabeçalho do bloco. Se uma transação diferente desejar modificar uma linha, ela usará o ID da transação para determinar se o bloqueio está ativo. Se o bloqueio estiver ativo, a sessão solicitará ser notificada quando o bloqueio for liberado. Caso contrário, a transação adquire o bloqueio.

Consulte Também:

Bloqueios de Tabela (TM)

Um bloqueio de tabela, também chamado de bloqueio de TM, é adquirido por uma transação quando uma tabela é modificada por uma instrução INSERT, UPDATE, DELETE, MERGE, SELECT com a cláusula FOR UPDATE ou LOCK TABLE.

As operações DML exigem bloqueios de tabela para reservar o acesso DML à tabela em nome de uma transação e para evitar operações DDL que possam entrar em conflito com a transação.

Um bloqueio de tabela pode ser mantido em qualquer um dos seguintes modos:

Consulte Também:

Bloqueios e Chaves Estrangeiras

O Oracle AI Database maximiza o controle de simultaneidade de chaves pai em relação a chaves estrangeiras dependentes.

O comportamento de bloqueio depende de as colunas de chave estrangeira serem indexadas. Se as chaves estrangeiras não forem indexadas, a tabela filho provavelmente será bloqueada com mais frequência, ocorrerão deadlocks e a simultaneidade será diminuída. Por esse motivo, quase sempre as chaves estrangeiras devem ser indexadas. A única exceção é quando a chave primária ou exclusiva correspondente nunca é atualizada ou excluída.

Bloqueios e Chaves Estrangeiras Não Indexadas

O banco de dados adquire um bloqueio de tabela completo na tabela filho quando não existe índice na coluna de chave estrangeira da tabela filho, e uma sessão modifica uma chave primária na tabela pai (por exemplo, exclui uma linha ou modifica atributos de chave primária) ou mescla linhas na tabela pai.

Quando as duas condições a seguir forem verdadeiras, o banco de dados adquire um bloqueio completo da tabela filho:

Suponha que a tabela hr.departments seja um pai de hr.employees, que contém a chave estrangeira não indexada employees.department_id. A figura a seguir mostra uma sessão que modifica os atributos de chave primária do departamento 60 na tabela departments.

Figura 3: Mecanismos de bloqueio com chave estrangeira não indexada

Descrição da ilustração cncpt308.gif

Na Figura 12-3, o banco de dados adquire um bloqueio de tabela completo em employees durante a modificação da chave primária do departamento 60. Esse bloqueio permite que outras sessões consultem, mas não atualizem a tabela employees. Por exemplo, as sessões não podem atualizar os números de telefone do funcionário. O bloqueio de tabela nas releases employees imediatamente após a modificação da chave primária na tabela departments ser concluída. Se várias linhas no departments sofrerem modificações de chave primária, um bloqueio de tabela no employees será obtido e liberado uma vez para cada linha modificada no departments. Observação: A DML em uma tabela filho não adquire um bloqueio de tabela na tabela pai.

Bloqueios e Chaves Estrangeiras Indexadas

O banco de dados não adquire um bloqueio de tabela completo na tabela filho quando uma coluna de chave estrangeira na tabela filho é indexada e uma sessão modifica uma chave primária na tabela pai (por exemplo, exclui uma linha ou modifica atributos de chave primária) ou mescla linhas na tabela pai.

Um bloqueio na tabela pai impede que as transações adquiram bloqueios de tabela exclusivos, mas não impede que a DML na tabela pai ou filha durante a modificação da chave primária. Esta situação é preferível se ocorrerem modificações na chave primária na tabela pai enquanto ocorrerem atualizações na tabela filho. A Figura 12-4 mostra a tabela filha employees com uma coluna department_id indexada. Uma transação exclui o departamento 280 de departments. Essa exclusão não faz com que o banco de dados adquira um bloqueio de tabela completo na tabela employees, como no cenário descrito em "Bloques e Chaves Estrangeiras Não Indexadas".

Figura 4: Mecanismos de bloqueio com chave estrangeira indexada

Descrição da ilustração cncpt309.gif

Se a tabela filha especificar ON DELETE CASCADE, as exclusões da tabela pai poderão resultar em exclusões da tabela filha. Por exemplo, a exclusão do departamento 280 pode causar a exclusão de registros de employees para funcionários no departamento excluído. Nesse caso, as regras de espera e bloqueio são as mesmas que se você tivesse excluído linhas da tabela filho depois de excluir linhas da tabela pai.

Consulte Também:

Bloqueios DDL

Um bloqueio de DDL (dicionário de dados) protege a definição de um objeto de esquema enquanto uma operação DDL em andamento age ou se refere ao objeto.

Somente objetos de esquema individuais que são modificados ou referenciados são bloqueados durante operações DDL. O banco de dados nunca bloqueia todo o dicionário de dados.

O Oracle AI Database adquire um bloqueio DDL automaticamente em nome de qualquer transação DDL que o exija. Os usuários não podem solicitar explicitamente bloqueios DDL. Por exemplo, se um usuário criar um procedimento armazenado, o Oracle AI Database adquirirá automaticamente bloqueios DDL para todos os objetos de esquema referenciados na definição do procedimento. Os bloqueios DDL impedem que esses objetos sejam alterados ou eliminados antes da conclusão da compilação do procedimento.

Bloqueios DDL exclusivos

Um bloqueio DDL exclusivo impede que outras sessões obtenham um bloqueio DDL ou DML.

A maioria das operações DDL requer bloqueios DDL exclusivos para um recurso a fim de evitar interferência destrutiva com outras operações DDL que possam modificar ou fazer referência ao mesmo objeto de esquema. Por exemplo, DROP TABLE não tem permissão para eliminar uma tabela enquanto ALTER TABLE está adicionando uma coluna a ela e vice-versa.

O DDL exclusivo é o último durante a execução da instrução DDL e o commit automático. Durante a aquisição de um bloqueio DDL exclusivo, se outro bloqueio DDL for mantido no objeto de esquema por outra operação, a aquisição aguardará até que o bloqueio DDL mais antigo seja liberado e, em seguida, prosseguirá.

Consulte Também: "Compartilhar Bloqueios DDL" descreve situações em que bloqueios exclusivos não são necessários para evitar interferência destrutiva

Compartilhar Bloqueios DDL

Um bloqueio DDL de compartilhamento para um recurso impede interferência destrutiva em operações DDL conflitantes, mas permite a simultaneidade de dados para operações DDL semelhantes.

Por exemplo, quando uma instrução CREATE PROCEDURE é executada, a transação que a contém adquire bloqueios DDL de compartilhamento para todas as tabelas referenciadas. Outras transações podem criar simultaneamente procedimentos que fazem referência às mesmas tabelas e adquirir bloqueios DDL de compartilhamento simultâneos nas mesmas tabelas, mas nenhuma transação pode adquirir um bloqueio DDL exclusivo em qualquer tabela referenciada.

Um bloqueio DDL de compartilhamento dura pela duração da execução da instrução DDL e do commit automático. Assim, uma transação que contém um bloqueio DDL de compartilhamento garante que a definição do objeto de esquema referenciado permaneça constante durante a transação.

Bloqueios de Parse Quebráveis

Um bloqueio esparso é mantido por uma instrução SQL ou uma unidade de programa PL/SQL para cada objeto de esquema ao qual ele faz referência.

Os bloqueios de parsing são adquiridos para que a área SQL compartilhada associada possa ser invalidada se um objeto referenciado for alterado ou eliminado. Um bloqueio de parsing é chamado de bloqueio de parsing que pode ser interrompido porque ele não permite nenhuma operação DDL e pode ser interrompido para permitir operações DDL conflitantes.

Um bloqueio de parsing é adquirido no pool compartilhado durante a fase de parsing da execução da instrução SQL. O bloqueio será mantido enquanto a área SQL compartilhada dessa instrução permanecer no shared pool.

Consulte Também: "Shared Pool"

Bloqueios do sistema

O Oracle AI Database usa vários tipos de bloqueios de sistema para proteger estruturas internas de banco de dados e memória. Esses mecanismos são inacessíveis aos usuários porque os usuários não têm controle sobre sua ocorrência ou duração.

Latches

Um latch é um mecanismo de serialização simples e de baixo nível que coordena o acesso de vários usuários a estruturas de dados, objetos e arquivos compartilhados.

As travas protegem os recursos de memória compartilhada contra danos quando acessados por vários processos. Especificamente, as travas protegem as estruturas de dados das seguintes situações:

Normalmente, uma única trava protege vários objetos na SGA. Por exemplo, processos em segundo plano, como DBW e LGWR, alocam memória do pool compartilhado para criar estruturas de dados. Para alocar essa memória, esses processos usam uma trava de pool compartilhado que serializa o acesso para impedir que dois processos tentem inspecionar ou modificar o pool compartilhado simultaneamente. Depois que a memória é alocada, outros processos podem precisar acessar áreas de pool compartilhado, como o cache de biblioteca, que é necessário para análise. Nesse caso, os processos travam apenas o cache da biblioteca, não todo o pool compartilhado.

Ao contrário das travas de enfileiramento, como bloqueios de linha, as travas não permitem que as sessões sejam enfileiradas. Quando uma trava se torna disponível, a primeira sessão a solicitar a trava obtém acesso exclusivo a ela. O fenômeno de giro de trava ocorre quando um processo solicita repetidamente uma trava em um loop, enquanto colocação em espera de trava ocorre quando um processo libera a CPU antes de renovar a solicitação de trava.

Normalmente, um processo Oracle adquire uma trava por um tempo extremamente curto enquanto manipula ou observa uma estrutura de dados. Por exemplo, ao processar uma atualização de salário de um único funcionário, o banco de dados pode obter e liberar milhares de latches. A implementação de travas é dependente do sistema operacional, especialmente no que diz respeito a se e quanto tempo um processo espera por uma trava.

Um aumento na trava significa uma diminuição na simultaneidade. Por exemplo, operações excessivas de hard parse criam contenção para o latch do cache da biblioteca. A view V$LATCH contém estatísticas detalhadas de uso de latch para cada latch, incluindo o número de vezes que cada latch foi solicitado e esperado.

Consulte Também:

Mutexes

Um objeto de exclusão mútua (mutex) é um mecanismo de baixo nível que impede que um objeto na memória expire ou seja corrompido quando acessado por processos simultâneos. Um mutex é semelhante a uma trava, mas enquanto uma trava normalmente protege um grupo de objetos, um mutex protege um único objeto.

Mutexes oferecem vários benefícios:

Bloqueios internos

Bloqueios internos são mecanismos de nível superior, mais complexos do que travas e mutexes e servem a vários propósitos.

O banco de dados usa os seguintes tipos de bloqueios internos:

Consulte Também: "Cache do Dicionário de Dados"

Visão Geral de Bloqueios de Dados Manuais

Você pode substituir manualmente os mecanismos de bloqueio padrão do Oracle AI Database.

O Oracle AI Database executa o bloqueio automaticamente para garantir a simultaneidade, a integridade e a consistência da leitura no nível da instrução. No entanto, a substituição do bloqueio padrão é útil em situações como a seguinte:

Você pode substituir o bloqueio automático do Oracle AI Database no nível da sessão ou da transação. No nível da sessão, uma sessão pode definir o nível de isolamento de transação necessário com a instrução ALTER SESSION. No nível da transação, as transações que incluem as seguintes instruções SQL substituem o bloqueio padrão do Oracle AI Database:

Os bloqueios adquiridos pelas instruções anteriores são liberados depois que a transação termina ou um rollback para liberá-los do ponto de salvamento.

Se o bloqueio padrão do Oracle AI Database for substituído em qualquer nível, o administrador do banco de dados ou o desenvolvedor do aplicativo deverá garantir que os procedimentos de bloqueio de substituição operem corretamente. Os procedimentos de bloqueio devem satisfazer os seguintes critérios: a integridade dos dados é garantida, a simultaneidade de dados é aceitável e os deadlocks não são possíveis ou são tratados adequadamente.

Consulte Também:

Visão Geral de Bloqueios Definidos pelo Usuário

Com os serviços do Oracle AI Database Lock Management, você pode definir seus próprios bloqueios para um aplicativo específico.

Por exemplo, você pode criar um bloqueio para serializar o acesso a um log de mensagens no sistema de arquivos. Como um bloqueio de usuário reservado é o mesmo que um bloqueio do Oracle AI Database, ele tem toda a funcionalidade de bloqueio do Oracle AI Database, incluindo detecção de deadlock. Os bloqueios do usuário nunca entram em conflito com os bloqueios do Oracle AI Database, porque eles são identificados com o prefixo UL.

Os serviços do Oracle AI Database Lock Management estão disponíveis por meio de procedimentos no pacote DBMS_LOCK. Você pode incluir instruções em blocos PL/SQL que:

Consulte Também:


Legenda da Nota de Rodapé

Nota de rodapé 1:

Ao processar um commit de duas fases distribuído, o banco de dados pode impedir brevemente o acesso de leitura em circunstâncias especiais. Especificamente, se uma consulta começar entre as fases de preparação e confirmação e tentar ler os dados antes da confirmação, o banco de dados poderá escalar um bloqueio do nível de linha para o nível de bloco para garantir a consistência de leitura.