Quantidade de redo gerado durante user-managed backup

Vamos falar brevemente sobre a quantidade de dados de redo gerados durante um backup com user-managed backup ou como é popularmente chamado begin backup e end backup. O RMAN é a ferramenta mais recomendada para executar backup e recovery de uma base de dados Oracle, porém sabemos que isso nem sempre acontece e muitos DBAs pelo mundo a fora ainda preferem fazer os seus backup com o método manual. Claro que há cenários em que podemos fazer via storage um snapshot dos discos/filesystems onde o banco está armazenado e isso normalmente é muito mais rápido, mas a discussão aqui é outra. O RMAN está presente no Oracle desde a versão 8 e já não é mais desculpa dizer que não conhece a ferramenta.

Meu intuito com esse artigo é apresentar uma informação que para muitos é desconhecida. Quando fazemos backup utilizando o método user-managed backup geramos muito mais dados de redo do que o necessário. Na documentação oficial da Oracle é citado que quando o banco de dados ou a tablespace é colocada em modo backup (begin backup) o primeiro DML em um bloco o leva inteiro para o redo log buffer e não apenas as alterações realizadas.

Redo Data

Veja o que diz na documentação:

In backup mode, the database copies whole changed data blocks into the redo stream.

Vamos simular o cenário então.

Vou primeiramente criar uma tabela para testarmos:

SQL> create table teste tablespace users as select * from dba_objects;

Table created.

Agora vamos habilitar o autotrace na nossa sessão para ver as estatísticas geradas em cada operação e vamos realizar um update:

SQL> set autotrace traceonly statistics
SQL> update teste set object_name='tablelore' where object_id=1000;

1 row updated.


Statistics
----------------------------------------------------------
	  9  recursive calls
	  3  db block gets
       1610  consistent gets
       1529  physical reads
	  0  redo size
	865  bytes sent via SQL*Net to client
	870  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

Como podemos observar acima nenhum redo foi gerado. Vou fazer um novo update no object_id 1001:

SQL> update teste set object_name='tablelore' where object_id=1001;

1 row updated.


Statistics
----------------------------------------------------------
	  5  recursive calls
	  1  db block gets
       1603  consistent gets
	  0  physical reads
	  0  redo size
	865  bytes sent via SQL*Net to client
	870  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

Novamente nenhum redo foi gerado, porém as leituras físicas zeraram, o que significa que estamos falando do mesmo bloco de dados que agora já estava em cache. Vamos adiante…

Vou desabilitar o autotrace e colocar a tablespace USERS em modo backup:

SQL> set autotrace off
SQL> alter tablespace users begin backup;

Tablespace altered.

Vou habilitar novamente o autotrace e reexecutar os updates com valores diferentes só para mostrar que estamos realmente alterando dados:

SQL> set autotrace traceonly statistics
SQL> update teste set object_name='loredatatable' where object_id=1000;

1 row updated.


Statistics
----------------------------------------------------------
	  4  recursive calls
	  2  db block gets
       1603  consistent gets
	  0  physical reads
       8740  redo size
	865  bytes sent via SQL*Net to client
	874  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

Opa, agora sim tivemos um montante bem grande de redo gerado, porque estou dizendo que é grande? Porque o bloco inteiro foi copiado para o redo log buffer. Vamos executar um update no mesmo bloco e ver o que acontece:

SQL> update teste set object_name='tablelore' where object_id=1001;

1 row updated.


Statistics
----------------------------------------------------------
	  0  recursive calls
	  1  db block gets
       1534  consistent gets
	  0  physical reads
	388  redo size
	866  bytes sent via SQL*Net to client
	870  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

Viu só? O valor é baixo desta vez porque o bloco já foi copiado para o redo log buffer, então o Oracle só grava as alterações (changed vectors).
Vamos fazer a mesma coisa só que para outro bloco de dados, vou atualizar agora o object_id=35000:

SQL> update teste set object_name='tablelore' where object_id=35000;

1 row updated.


Statistics
----------------------------------------------------------
	  5  recursive calls
	  1  db block gets
       1603  consistent gets
	  0  physical reads
       8580  redo size
	866  bytes sent via SQL*Net to client
	871  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

Mais uma vez uma boa quantidade de redo.
Para finalizar vamos atualizar o object_id 35001 e constatar que serão gravadas somente as alterações no log buffer:

SQL> update teste set object_name='tablelore' where object_id=35001;

1 row updated.


Statistics
----------------------------------------------------------
	  5  recursive calls
	  1  db block gets
       1603  consistent gets
	  0  physical reads
	336  redo size
	866  bytes sent via SQL*Net to client
	871  bytes received via SQL*Net from client
	  3  SQL*Net roundtrips to/from client
	  1  sorts (memory)
	  0  sorts (disk)
	  1  rows processed

SQL> rollback;

Rollback complete.

SQL> alter tablespace users end backup;

Tablespace altered.

Interessante né? Você pode executar o mesmo teste e vai chegar na mesma conclusão.
Foi um artigo bem breve, mas interessante sobre o funcionamento do banco de dados Oracle.

Abraços e até mais,

Franky