GPO ( Grupo de Profissionais Oracle )
A maior comunidade Oracle do Brasil !

Concorrência e Consistência dos Dados (Locks)

Olá

Nesse primeiro Post, tenho a intenção de mostrar de forma resumida, prática e simples o conceito de concorrência e consistência de dados, enfim os nossos locks de cada dia.

Se os banco de dados tivessem apenas um único usuário, muitos dos nossos problemas seriam resolvidos (Tudo bem que criaríamos muitos outros, mas isso não vem ao caso agora), os dados poderiam sofrer modificações em diversas horas e até ao mesmo tempo. Porém como dois corpos não ocupam o mesmo lugar no espaço, em bancos de dados “multi usuário”, as transações podem tentar atualizar os mesmos dados ao mesmo tempo. Então por isso os bancos de dados devem ter e possuem um controle de concorrência afim de manter a consistência dos dados, para os outros usuários.

Concorrência de Dados quer dizer que os usuários(vários) podem acessar os mesmos dados ao mesmo tempo. Já Consistência de dados quer dizer que os usuários podem ter uma visão consistente sólida e real dos dados, incluindo as alterações que o próprio usuário esta realizando e as alterações feitas por outros usuários.

Help_1: Caso algum iniciante tenha a seguinte dúvida:

  • Se algum usuário estiver atualizando uma tabela, eu vou ver os valores antigos ou os alterados ?

Resposta : Em primeiro lugar, caso você tenha essa dúvida é sinal que está na hora de aprender sobre segmentos de UNDO, mas clareando respondendo a dúvida, sempre quando vamos atualizar,deletar ou inserir algum dado em alguma tabela, o Oracle usa os segmentos de UNDO para armazenar os blocos de dados antigos e como resultado, fornecem os valores anteriores das linhas para qualquer usuário que emite uma instrução select antes de a transação sofrer commit.Então se alguém estiver fazendo alguma modificação, quando outra pessoa executar uma instrução select, essa somente verá os dados armazenados no segmento de UNDO ou seja os antigos, até que o commit, seja executado.( Vale a Pena pesquisar sobre o assunto).

Mecanismo de Locks (Ou bloqueio)

Os SGBDs tem por default um mecanismo de lock(bloqueio) para resolver os problemas realcionados a integridade, consistência e concorrência de dados. Os Locks são mecanismos que impedem que transações atualizem os mesmos dados ao mesmo tempo.

  • Controlam o acesso concorrente ao banco de dados
  • Impede atualizações simultâneas do mesmo dado
  • É liberado ao final de cada transação (COMMIT,ROLLBACK)

Tempo de Duração

Todos os bloqueios adquiridos pelas declarações dentro de uma transação são mantidos para a duração da operação, impedindo a interferência destrutiva, incluindo leituras sujas e perda de atualizações. As alterações introduzidas pelas instruções SQL de uma transação só se tornam visíveis para outras transações que começam após que a primeira transação seja confirmada (Commit).
O Oracle libera todos os bloqueios adquiridos pelas declarações dentro de uma transação quando você confirmar ou desfazer a transação. A Oracle também libera os bloqueios adquiridos após um ponto de salvamento(savepoint) quando existe reversão para o ponto de salvamento.

DEADLOCK

Um deadlock ocorre quando dois ou mais segmentos do controle estão bloqueadas, cada um à espera de um recurso mantido por outro segmento.Elas ficam aguardando que uma libere um determinado recurso para que outra o utilize. Existe outras fontes na internet os quais detalham melhor esse conceito e os tipos de Lock.

Vamos forçar o acontecimento de Locks.

1_Vamos Criar e popular a  tabela HT_LOCK.

SQL> CREATE TABLE HT_LOCK (

ID_LOCK VARCHAR2(1),

COD_LOCK VARCHAR2(1));

Table created.

SQL> INSERT INTO  HT_LOCK VALUES (1,'A');

SQL> INSERT INTO  HT_LOCK VALUES (2, 'B');

SQL> INSERT INTO  HT_LOCK VALUES (3, 'C');

SQL> INSERT INTO  HT_LOCK VALUES (4, 'D');

4  row created.

SQL> SELECT * FROM HT_LOCK;

ID_LOCK  COD_LOCK

---                ---

1                  A

2                  B

3                  C

4                  D

4 rows selected.

SQL> commit ;

Commit complete.

2_Vamos efetuar um UPDATE nessa Tabela com usuários diferentes;

SQL>UPDATE HT_LOCK SET ID_LOCK='0' WHERE ID_LOCK='4';

1 linha atualizada.

SQL> UPDATE HUDSON.HT_LOCK SET ID_LOCK='9' WHERE ID_LOCK='2';

1 linha atualizada.

3_Agora vamos verificar quais usuários estão gerando algum tipo de lock.

SQL>  SELECT OBJECT_ID,SESSION_ID,ORACLE_USERNAME FROM  V$LOCKED_OBJECT;

OBJECT_ID SESSION_ID ORACLE_USERNAME

---------- ---------- ------------------------------

19996           14                    HUDSON

19996           21                     SYSTEM

2 linhas selecionadas.

Help_2 A Visão V$LOCKED_OBJECT listas todos os bloqueios adquiridos por todas as transações no sistema. Isso mostra que as sessões estão mantendo bloqueios DML em que objetos e de que modo.

Então Temos dois Usuários com locks em um objeto de mesmo ID, logo se trata do mesmo objeto..

Agora vamos descobrir que objeto é esse ;

SQL> SELECT OBJECT_NAME, OBJECT_TYPE,OBJECT_ID FROM DBA_OBJECTS WHERE  OBJECT_ID  = 19996;

OBJECT_NAME                    OBJECT_TYPE          OBJECT_ID

------------------------------ ------------------- ------         ----

HT_LOCK                        TABLE                             19996

Agora sabemos que esse lock é realizado na Tabela HT_LOCK .

Eu mostrei como localizar quais são os usuários os quais estão gerando lock em alguma tabela e quais tabelas são essas de forma separada para melhor entendimento, mas isso também poderia ser feito de uma forma só com o select abaixo :

SQL>SELECT A.OBJECT_ID, A.SESSION_ID, A.ORACLE_USERNAME, B.OBJECT_NAME , B.OBJECT_TYPE FROM v$locked_object A , DBA_OBJECTS B

WHERE A.OBJECT_ID = B.OBJECT_ID;

OBJECT_ID      SESSION_ID ORACLE_USERNAME            OBJECT_NAME

--------------- --------------- ------------------------------ ----------------------------------

19996              21            SYSTEM                                            HT_LOCK

19996              14            HUDSON                                           HT_LOCK

Agora se um sessão de um usuário gerar um lock em alguma tabela e se a mesma  for mal finalizada  ela ira ficar com o status de inativa no banco de dados, e esse lock somente irá sumir quando o processo de segundo plano ou background PMON aplicar rollback na transação, e assim remover os locks nas linhas afetadas.

Mas caso por algum problema PMON demorar para aplicar o rollback e remover os locks, você pode matar essa sessão pendente e assim retirar o lock, da seguinte forma.

SQL> SELECT SID,SERIAL#,USERNAME,STATUS FROM V$SESSION WHERE SID =  14  --(ESSE VALOR É EQUIVALENTE AO VALOR DO CAMPO SESSION_ID DA VISÃO v$locked_object)

SID    SERIAL# USERNAME             STATUS

-------- ---------- ------------------------------ --------

14         61          HUDSON                  INACTIVE

Após obter o SID, e o SERIAL# de sessão vamos forçar a sua finalização com o comando :

ALTER SYSTEM KILL SESSION ‘301,9797’ IMMEDIATE;

A Minha intenção nesse Post foi mostrar como ocorre um lock e como entender o processo de identificação e finalização :

Porém existem scripts que podem fazer tudo, ou andar um bom caminho segue esse script do Rodrigo Almeida publicado em 06 novembro 2005  ás  15:03 no link.

SET LINESIZE 500

SET PAGESIZE 1000

SET VERIFY OFF

COLUMN owner FORMAT A20

COLUMN username FORMAT A20

COLUMN object_owner FORMAT A20

COLUMN object_name FORMAT A30

COLUMN locked_mode FORMAT A15

SELECT b.session_id AS sid,

NVL(b.oracle_username, '(oracle)') AS username,

a.owner AS object_owner,

a.object_name,

Decode(b.locked_mode, 0, 'None',

1, 'Null (NULL)',

2, 'Row-S (SS)',

3, 'Row-X (SX)',

4, 'Share (S)',

5, 'S/Row-X (SSX)',

6, 'Exclusive (X)',

b.locked_mode) locked_mode,

b.os_user_name

FROM   dba_objects a,

v$locked_object b

WHERE  a.object_id = b.object_id

ORDER BY 1, 2, 3, 4;

SET PAGESIZE 14

SET VERIFY ON

Referências

Share

You may also like...

2 Responses

  1. Carlos Santana disse:

    Muito Bom Hudson,

    Bem citado essa questão da concorrência dos dados e do processo de lock.
    Abs

  2. Hudson Santos disse:

    Andre

    Realmente, não sei porque alterei o sid e o serial do exemplo.
    mas o importante é passar o conceito ..rs

    Abraços!

Deixe um comentário

O seu endereço de e-mail não será publicado.