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.
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