Apagando todos objetos de um esquema

É muito comum ter várias aplicações numa única base do Oracle organizadas por esquemas. Se for este o seu caso, você se verá com alguma frequência para migrar um esquema inteiro da base de produção para homologação, do teste para homologação e por aí vai. Exportar os objetos e importar é muito simples, tanto com utilizando o IMP e EXP comuns até a versão 9i como com o Data Pump no 10g em diante:

Com o imp e exp:

exp usuario@nome_base_origem file=dump_esquema.dmp owner=nome_esquema
imp usuario@nome_base_destino file=dump_esquema.dmp fromuser=nome_esquema touser=nome_esquema

Com o data pump:

expdp usuario@nome_base_origem dumpfile=data_pump_dir dumpfile=dump_esquema.dmp schemas=nome_esquema
impdp usuario@nome_base_destino dumpfile=data_pump_dir dumpfile=dump_esquema.dmp schemas=nome_esquema

Bom, até aí não há muito motivo para espanto, é algo trivial. O detalhe é quando você precisa apagar todos os objetos já existentes antes de importar os novos. Para isso, um pouco de SQL sempre ajuda:

SELECT 'DROP TABLE ' || owner || '.' || TABLE_NAME || ' CASCADE CONSTRAINTS;'
  FROM dba_tables
  WHERE owner = 'NOME_ESQUEMA'';
 
SELECT 'DROP ' || object_type || ' ' || owner || '.' || object_name || ';'
  FROM dba_objects
  WHERE
    object_type != 'PACKAGE BODY' AND
    owner = 'NOME_ESQUEMA';

É claro que você poderia criar uma função para fazer tudo isso (limpar os objetos e importar o dump) numa tacada só. Mas eu diria que dois comandos SQLs não são motivo para tanto. :-)

Shell Scrip para backup manual no Oracle no Linux

… ou YASHTBODB: Yep, Another Shell Script To Backup Oracle DataBase!

Já faz algum tempo que utilizo Shell Script para fazer backup no Oracle. Na verdade eu prefiro utilizar outras linguagens de programação, particularmente o PERL, para não precisar ficar chamando o SQL*Plus toda hora. Mas como existe uma barreira cultural por aqui, acabou ficando tudo em Shell Script mesmo. Bom, ocorre que chegou a hora de aposentá-los em favor do RMAN. Sim, com o uso do RAC junto com o ASM, backup manual ou “user managed backup” como a Oracle gosta de dizer, perdeu completamente o sentido. Além disso, no Oracle 10g, o Database Control implementou uma série de alertas sofisticados bem mais eficientes que o singelo script aqui em questão. Estou terminando de implantar o RMAN para todos os últimos servidores e então os últimos scripts cairão finalmente no ostracismo. Então estou publicando-os aqui, para que sirvam de referência futura.

Requisitos

Rotinas executadas a cada 30 minutos:

  • Cópia dos archives para outro servidor;
  • Criação de alerta se alguma partição possuir mais de 80% e 95% de ocupação.

Rotinas executadas a cada 24 horas:

  • Rodar o analyze em todos objetos;
  • Fazer backup lógico full;
  • Copiar backup lógico para outro servidor;
  • Verificar a integridade dos datafiles;
  • Fazer cópia on-line dos datafiles permanentes para outro servidor;
  • Verificar o volume de origem e o copiado dos datafiles;
  • Fazer cópia do control_file em modo binário e lógico;
  • Fazer cópia do spfile;
  • Apagar archives com mais 8 dias;
  • Verificar se algum tablespace está com mais de 80% de ocupação;
  • Verificar todos os erros ocorridos no alert;
  • Renomear o alert para um nome com o SID e data

Rotinas executadas a cada 7 dias:

  • Cópia off-line dos datafiles permanentes para outro servidor;
  • Cópia do spfile

Rotina mensal (realizadas no último dia de cada mês):

  • Rodar scripts específicos de aplicações
  • Arquivar todos os logs (adump, bdump, cdump, udump e backup logs) em uma pasta ‘old’

Outros requisitos:

  • Criar um log contendo todos os erros ocorridos durante todas operações de backup;
  • Registrar no log a duração de todas operações longas;
  • Registrar no log o espaço disponível em cada partição de disco;
  • Enviar um e-mail com o log ao término de cada operação de backup;
  • Parametrizar o script de forma a utilizar o mesmo script para vários servidores distintos.

Preparação

Antes de mais nada, é preciso criar um usuário no SO e no Oracle. É preciso se assegurar que o usuário em questão tenha acesso às pastas que ele irá copiar. Existem pelo menos umas 4 formas de se fazer isso:

  • Utilizar o próprio usuário Oracle. A vantagem de usar o usuário Oracle do SO, é não precisar colocar senha no script, por outro lado a pessoa que administra o script acaba tendo autorização para acessar o banco diretamente sem senha e com poderes de SYSDBA. Em termos de segurança, isto não é recomendado. No entanto, os backups off-lines e backups de spfile exigem o usuo de um usuário com permissões de SYSDBA ou SYSOPER, então acaba fazendo sentido utilizar o usuário Oracle do SO para estas operações;
  • Alterar as permissões nas pastas do banco de dados para permitir a leitura para que qualquer usuário do SO (o terceiro dígito no sistema octal de permissões). Não gosto desta solução por problemas de segurança, uma vez que não apenas o usuário de backup como outros também terão acesso aos arquivos do Oracle. Se for para fazer isso, ainda é melhor usar o usuário Oracle do SO mesmo para tudo;
  • Alterar os grupos donos dos arquivos e pastas a serem utilizados. Também não é uma boa idéia, uma vez que ao criar um novo datafile, ele é criado com o grupo oinstall por padrão. A cada vez que um novo datafile é criado, você teria de alterar o grupo do datafile;
  • Adicionar o usuário de backup ao grupo oinstall. Pode não ser uma solução muito segura, mas veja que os datafiles são criados com a permissão 640 por padrão. O que significa que o usuário em questão só poderá ler os datafiles sem poder alterá-los, o que me parece bem razoável. Mesmo assim, você deverá acertar o acesso de algumas pastas e arquivos para que você possa gravar nelas, como a pasta onde o próprio script vai ficar e onde ele vai gerar os logs e os backups lógicos. Esta será a opção utilizada para a maioria das operações de backup. A excessão, como citado anteriormente fica para o backup do spfile e backup off line.

Para criar um usuário no SO que faça parate do grupo ‘oinstall’ (realmente estou supondo que você usou o nome dos usuários e grupos de usuáros padrões da instalação):

/usr/sbin/useradd -m -p senha -g oinstall -c 'Usuário que dispara os scripts de backup' backup

O mesmo usuário do SO deverá ter um correspondente dentro do banco de dados:

CREATE USER backup IDENTIFIED BY senha
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users
;

Se você quiser utilizar um usuário a parte mas não quer colocar a senha do usuário nos scripts (que é o que foi feito no nosso exemplo), pode criar o usuário com o comando abaixo:

CREATE USER backup IDENTIFIED EXTERNALLY
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users
;

Mas para utilizar usuários autenticados externamente (pelo SO) não esqueça de setar no ‘init.ora’ os seguintes parâmetros:

remote_os_authent=FALSE
os_authent_prefix=''

O parâmetro ‘os_authent_prefix’ é opcional e permite que o nome no SO seja idêntico ao nome no banco de dados. Já o parâmetro ‘remote_os_authent’ é vital para garantir a segurnaça do banco de dados. O padrão do parâmetro é ‘FALSE’ e ninguém em sã consciência utiliza este parâmetro como ‘TRUE’.

Depois de criar o usuário precisamos conceder as permissões adequadas para ele:

GRANT CREATE SESSION TO backup;
GRANT ALTER SESSION TO backup;
GRANT ALTER DATABASE TO backup;
GRANT ALTER SYSTEM TO backup;
GRANT MANAGE TABLESPACE TO backup;
GRANT ANALYZE ANY TO backup;
GRANT ANALYZE ANY DICTIONARY TO backup;
GRANT EXP_FULL_DATABASE TO backup;

Lembre-se de O usuário também deve ter um tablespace com alguma quota para criar as tabelas de logs do backup lógico (coisas do data pump a partir do 10g). O comando CREATE USER cria o usuário, com a senha: ‘senha’. Depois concedemos privilégio para o usuário se conectar no banco de dados em CREATE SESSION. O privilégio ALTER SESSION será utilizado para ajudar a identificar o backup lógico do control file enquanto o privilégio ALTER DATABASE é utilizado para realizar o backup físico e lógico do control file propriamente dito. O privilégio ALTER SYSTEM é necessário para realizar o checkpoint e o rotacionamento dos logs durante o backup físico on line enquanto o privilégio MANAGE TABLESPACE permite a operação de backup on line propriamente dita. Note que aqui a permissão de leitura dos datafiles pelo usuário do SO é necessária também. Depois temos os privilégios ANALYZE e ANALYZE ANY DICTIONARY necessários para as atualizações de estatísticas das tabelas e índices. Note que o privilégio ANALYZE ANY DICTIONARY surge apenas no Oracle 10g, não existindo nem sendo necessário em versões anteriores. Por último vem o privilégio EXP_FULL_DATABASE que é necessário para o backup lógico.

Se você for utilizar o Data Pump (muito recomendado e utilizado no nosso exemplo), a nova ferramente de backup lógico da Oracle a partir da versão 10g, você deverá utilizar também os seguintes comandos SQL:

CREATE DIRECTORY data_pump_dir_ORACLE_SID AS '/u03/app/oracle/admin/ORA_SID/exp';
GRANT READ, WRITE ON DIRECTORY data_pump_dir_ORA_SID

Onde ‘ORACLE_SID’ é o nome do seu banco de dados oracle. É claro que o ponto de montagem ‘/u03′ é específico do padrão que adoto nos meus servidores. Substitua o caminho do diretório para aquele que você reservou no seu servidor. Lembre-se que este diretório deve ser criado manualmente e o usuário ‘backup’ ou o grupo ‘oinstall’ do SO devem ter permissões de leitura e gravação neste diretório:

mkdir -p /u03/app/oracle/admin/ORA_SID/exp
chown backup:oinstall /u03/app/oracle/admin/ORA_SID/exp
chmod 755/u03/app/oracle/admin/ORA_SID/exp

Outras permissões deverão ser acertadas para o usuário de backup no SO como a permissão para apagar os archives (com uma permissão 770 na pasta por exemplo). Alguns acertos podem ser um pouco chatos e devem ser realizados no servidor de destino onde os arquivos são copiados também.

Um último detalhe é que é preciso configurar o SSH sem senha entre os servidores onde está o servidor Oracle e e o que vai receber todos os backups. Meus testes com NFS mostraram que ele é menos estável que o SSH e a diferença de performance é mínima. Existem vários tutoriais sobre como fazer isso, inclusive este da própria Oracle. No meu caso eu criei um usuário backup e um usuário oracle no servidor de destino e gerei o ssh sem senha entre os usuários com mesmo nome nos servidores de origem e destino dos backups.

Funcionamento do Script

Algumas premissas foram assumidas antes de criar o script:

  • O mesmo script deveria ser utilizado independente do banco de dados que sofreria as operações. Para isso o script deve receber como parâmetro o nome do banco e todas as pastas devem receber o nome do banco também, seguindo as recomendações do OFA. Isto facilita e muito a utilização do mesmo script em vários servidores distintos ou quando temos mais de uma instância no mesmo servidor.
  • O mesmo script deveria ser utilizado para diversas operações diferentes. Para isso o script deve receber como parâmetro o nome da operação.
  • Excepto pelos parâmetros de nome da base e operação, todas as outras variáveis são identicas, sendo declaradas no início do script. Esta configuração é adequada para o caso onde se utiliza apenas um ORACLE_HOME para todas as bases do servidor, mas pode ser um problema em outros casos.
  • Ao invés de colocar todo o código SQL em arquivos separados e chamarmos eles pelo SQL*Plus, optei por colocar todo o códio SQL dentro do script e envia-lo para o SQL*Plus utilizando o redirecionamento conhecido como “here document”, que é algo como um < onde “…” é o código SQL.
  • Todas as chamadas do scripts seriam chamados a partir do crontab do usuário, mas isto não impede a chamada manual.
  • Cada etapa do backup é colocada em uma função separada, de forma a podermos realocar as etapas para diferentes situações em necessidades específicas (como em servidores de teste e produção). A forma como o script está configurado aqui é apenas um exemplo. Em produção, tenho uma série de outras funções específicas de nossas regras de negócio que foram removidas também.
  • O backup lógico aqui está sendo feito com o Data Pump, mas nada impede você de adaptar o script para utilizar a ferramenta tradicional de export da Oracle.

Variáveis de Ambiente

Antes de passar para os scripts de backup, segue abaixo algumas variáveis utilizadas não apenas pelos scripts em shell, como também os scripts em SQL. Vale a pena lembrar que quando os scripts são executados no modo não interativo (como quando chamados pelo cron) é comum que os arquivos .bashrc e .bash_profile ignorem suas configurações. Por via das dúvidas, vamos exportar todas as variáveis de ambiente do Oracle e outros que serão úteis em nossos scripts.

  • ORACLE_HOME : o diretório onde o SGDB Oracle foi instalado;
  • ORACLE_SID : o nome do banco de dados alvo das operações de backup;
  • SQLPATH : o diretório padrão do SQL*Plus para armazenamento de scripts SQL;
  • NLS_LANG : Diz respeito a localização e codificação de caracteres utilizados;
  • PATH : deve incluir o caminho para o diretório com os aplicativos Oracle;
  • dia : referência para saber a data em que a operação foi realizada. Gosto de utilizar o formato ano/mês/dia, pois é mais fácil de listar em órdem cronológica arquivos com este formato de data;
  • log : arquivo contendo o log de toda a operação;
  • arch_dest : local de destino local para os archives;
  • dump_dest : local de destino local para os backups lógicos;
  • remote_dest : nome ou ip do servidor remoto que receberá os backups
  • dados: nome dos pontos de montagem onde se encontram os datafiles;
  • oracle_mail : email para onde os logs e alertas serão enviados;

Chamadas no crontab

Segue aqui as chamadas utilizadas para acionar o script

00 06 1 * * /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base rotina_mensal
00 22 * * * /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base backup_noturno
00,30  * * * * /bin/bash /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base copia_archives

Note que para realizar as rotinas de backup off line, é preciso do privilégio de SYSDBA para fechar e abrir a instância. Então se você utiliza um usuário separado para o backup, deverá colocar a linha abaixo no crontab do usuário oracle do SO e não usuário backup.

00 00 * * 0 /u01/app/oracle/admin/nome_base/adhoc/backup.sh nome_base backup_off_line

O Script

Bom, chega de enrolação, segue abaixo o script. Se você encontrar algum erro (eu tive que tirar algumas coisas muito específicas aqui do trabalho) ou alguma forma de melhorar ele, por favor deixe um comentário ou mande um e-mail.

#!/bin/bash
######################################################################################
#	Arquivo: backup.sh                                                           #
#	Uso: Script para backup "user managed" de bancos de dados Oracle             #
#	Criado por: Fábio Telles                                                     #
#	Última alteração: 14/08/2008                                                 #
#	Motivo: Publicação                                                           #
######################################################################################
#	TODO: Refazer todo script em PERL ;-)                                        #
######################################################################################
 
# Verificação de parâmetros
ORACLE_SID=$1
operation=$2
if [ -z $operation ]; then
  echo "***** Favor definir a operação a ser executada"
  echo "***** chamada $0 $* ilegal"
  echo "***** uso: $0  "
  exit 2
fi
if [ -z $ORACLE_SID ]; then
  echo "***** Favor definir o nome do banco de dados"
  echo "***** chamada $0 $* ilegal"
  echo "***** uso: $0  "
  exit 2
fi
 
# Definição de variáveis (variáveis referenciadas fora do script precisam ser exportadas)
export ORACLE_SID
export ORACLE_BASE=/opt/app/oracle
export ORACLE_HOME=${ORACLE_BASE}/product/10.2.0/db_1
export LD_LIBRARY_PATH=${ORACLE_HOME}/lib
export SQLPATH=/u01/app/oracle/admin/${ORACLE_SID}/adhoc
export NLS_LANG=Portuguese_Brazil.WE8ISO8859P1
export PATH=$PATH:${ORACLE_HOME}/bin
export dia=`date +%Y-%m-%d`
export log=/u01/app/oracle/admin/${ORACLE_SID}/backup/${operation}_${dia}.log
export arch_dest=/u02/app/oracle/admin/${ORACLE_SID}/arch
export dump_dest=/u03/app/oracle/admin/${ORACLE_SID}/exp
export remote_dest=seu_servidor_backup
dados=(/u04 /u05)
oracle_mail=email_do_dba@sua_empresa.com.br
 
# Uma função para cada rotina
copia_archives() {
  rsync -t ${arch_dest}/* ${remote_dest}:${arch_dest} 2>> $log
  if [ $? -ne 0 ]; then
    cat $log | mail -s "Erros na cópia de archives de `uname -n` p/ $remote_dest em ${dia}" $oracle_mail
  fi
}
 
verifica_discos() {
  # Verifica se alguma partição montada tem mais de 80% e 95% de ocupação
  for part in `df -hlP -t ext3 | cut -c0-9` ;do
    df $part > /dev/null 2> /dev/null
    if [ $? -eq 0 ]; then
      mount=`df $part | tail -1 | awk '{print $6}'`
      percent=`df $part | tail -1 | awk '{print $5}'`
      if [ ${percent%\%} -gt 80 -a ${percent%\%} -lt 95 ]; then
        echo "Atenção: `uname -n` c/ $part montada em $mount está c/ $percent ocupado." >> $log
        cat $log | mail -s "Alerta de disco em `uname -n`!" $oracle_mail
      elif [ ${percent%\%} -ge 95 ]; then
        echo "ATENÇÃO URGENTE: `uname -n` c/ $part montada em $mount está c/ $percent ocupado." >> $log
        cat $log | mail -s "ALERTA CRÍTICO de disco em `uname -n`!" $oracle_mail
     fi
    fi
  done
}
 
analize() {
  echo "Analyze: analizando ${ORACLE_SID} em "`date +%R:%S` >> $log
  sqlplus -S / <<-EOF_ANALIZE
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/analyze.log
    EXECUTE dbms_stats.gather_database_stats();
    SPOOL OFF
    EXIT;
EOF_ANALIZE
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/analyze.log  >> $log 2>> $log
}
 
backup_logico() {
  echo "Backup lógico: removendo exports de ${dump_dest} em "`date +%R:%S` >> $log
  rm -v ${dump_dest}/${ORACLE_SID}_full_* >> $log 2>> $log
  echo "Backup lógico: export iniciado em "`date +%R:%S` >> $log
  expdp / full=y directory=data_pump_dir_${ORACLE_SID} dumpfile=${ORACLE_SID}_full_${dia}.dmp \
    logfile=${ORACLE_SID}_full_exp_${dia}.log
  tail -n 1 ${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log >> $log 2>> $log
  echo "Backup lógico: copiando dump para ${remote_dest}/${dump_dest}  em "`date +%R:%S` >> $log
  scp ${dump_dest}/${ORACLE_SID}_full_${dia}.dmp \
    ${remote_dest}:${dump_dest}/${ORACLE_SID}_full_${dia}.dmp >> $log 2>> $log
  scp ${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log \
    ${remote_dest}:${dump_dest}/${ORACLE_SID}_full_exp_${dia}.log >> $log 2>> $log
  echo "" >> $log
}
 
verifica_data_file() {
  echo "Verificação física on-line iniciada em "`date +%R:%S` >> $log
  sqlplus -S / <<-EOF_VERIFICA_DATA_FILE
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/db_verify.txt
    SELECT '!dbv file=' || file_name || ' 2>> ${SQLPATH}/db_verify.log'
      FROM dba_data_files
      ORDER BY tablespace_name, file_name;
    SPOOL OFF
    @db_verify.txt
    EXIT
EOF_VERIFICA_DATA_FILE
  egrep --color -n -B 7 -A 9 'Total Pages Failing.*(Data).*[^0]$' \
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  egrep --color -n -B 9 -A 7 'Total Pages Failing.*(Index).*[^0]$' \
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  egrep --color -n -B 14 -A 2 'Total Pages Marked Corrupt.*[^0]$' \
    ${SQLPATH}/db_verify.log >> $log 2>> $log
  echo "" >> $log 2>> $log
}
 
backup_fisico_on_line() {
  echo "Backup físico on-line: copiando data files para ${remote_dest} em "`date +%R:%S`  >> $log
  sqlplus -S / <<-EOF_BACKUP_ON_LINE
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/backup_on_line.txt
    SELECT 'ALTER SYSTEM CHECKPOINT;' FROM dual;
    SELECT command
      FROM (
        SELECT
          '2' ordem,
          tablespace_name,
          'ALTER TABLESPACE ' || tablespace_name || ' BEGIN BACKUP;' command
          FROM dba_tablespaces
          WHERE contents != 'TEMPORARY'
        UNION
        SELECT
          '3' ordem,
          a.tablespace_name,
          '!scp ' || file_name || ' ${remote_dest}:' || file_name || ' 2>> $log'   command
          FROM
            dba_data_files  a,
            dba_tablespaces b
          WHERE
            a.tablespace_name = b.tablespace_name AND
            b.contents != 'TEMPORARY'
        UNION
        SELECT
          '4' ordem,
          tablespace_name,
          'ALTER TABLESPACE ' || tablespace_name || ' END BACKUP;' command
          FROM dba_tablespaces
          WHERE contents != 'TEMPORARY'
      )
      ORDER BY tablespace_name, ordem;
    SELECT 'ALTER SYSTEM ARCHIVE LOG CURRENT;' FROM dual;
    SELECT 'EXIT;' FROM dual;
    SPOOL OFF
    SET PAGES 50
    SPOOL ${SQLPATH}/backup_on_line.log
    @${SQLPATH}/backup_on_line.txt
    SPOOL OFF
EOF_BACKUP_ON_LINE
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_on_line.txt >> $log 2>> $log
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_on_line.log >> $log 2>> $log
  echo "" >> $log
}
 
compara_backup_fisico() {
  echo "Backup físico on-line: comparando origem e destino em "`date +%R:%S`  >> $log
  echo "Backup físico on-line: origem =" >> $log 2>> $log
  for p in ${dados[*]}; do
    du -hs ${p}/oradata/${ORACLE_SID} --exclude temp* >> $log 2>> $log
  done
  echo "Backup físico on-line: destino =" >> $log 2>> $log
  for p in ${dados[*]}; do
    ssh $remote_dest du -hs ${p}/oradata/${ORACLE_SID} >> $log 2>> $log
  done
  echo "" >> $log
}
 
backup_control_file() {
  echo "Backup físico on-line: copiando control files para ${ORACLE_HOME}/dbs em "`date +%R:%S`  >> $log
  sqlplus -S / <<-EOF_BACKUP_ON_LINE
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/backup_control_file.txt
    SELECT
      '!cp ' || par.value || '/' ||
      ins.instance_name || '_ora_' ||
      pro.spid || '_control_file.trc ${ORACLE_HOME}/dbs/control_file_back.sql 2>> $log'
      FROM
        v\$parameter par,
        v\$instance ins,
        v\$process pro,
        v\$session ses
      WHERE
        par.name='user_dump_dest' AND
        ses.sid = SYS_CONTEXT ('USERENV', 'SID') AND
        ses.paddr = pro.addr
     ;
    SPOOL OFF
    SPOOL ${SQLPATH}/backup_control_file.log
    ALTER SESSION SET TRACEFILE_IDENTIFIER = 'control_file';
    ALTER DATABASE BACKUP CONTROLFILE TO TRACE;
    ALTER SESSION SET TRACEFILE_IDENTIFIER = '';
    @${SQLPATH}/backup_control_file.txt
    ALTER DATABASE BACKUP CONTROLFILE TO '${ORACLE_HOME}/dbs/control_file_back.bin' REUSE;
    SPOOL OFF
EOF_BACKUP_ON_LINE
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_control_file.txt >> $log 2>> $log
  egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_control_file.log >> $log 2>> $log
  echo "" >> $log
}
 
backup_dbs() {
  echo "Backup físico on-line: copiando ${ORACLE_HOME}/dbs para \
    ${remote_dest}:${ORACLE_HOME}/dbs_${ORACLE_SID}.tar.bz2 em "`date +%R:%S`  >> $log
  cd $ORACLE_HOME
  tar -cjf ${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2 dbs >> $log 2>> $log
  scp ${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2 \
    ${remote_dest}:${SQLPATH}/dbs_${ORACLE_SID}.tar.bz2 >> $log 2>> $log
}
 
limpa_archives() {
  echo "Archives: removendo archives com mais de 8 dias de $arch_dest em "`date +%R:%S` >> $log
  find $arch_dest -daystart -mtime +8 -exec rm -fv \{\} \; >> $log 2>> $log
  echo "" >> $log
}
 
verifica_alert() {
  echo "Alert: erros encontrados =>" >> $log
  egrep --color -n -B 2 '(ORA-|SP2-)' \
    /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log >> $log 2>> $log
  echo "Alert: renomeando bdump/alert_${ORACLE_SID}.log para ${ORACLE_SID}_${dia}.log" >> $log
  if [ -f /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log ]; then
    mv /u01/app/oracle/admin/${ORACLE_SID}/bdump/alert_${ORACLE_SID}.log \
      /u01/app/oracle/admin/${ORACLE_SID}/bdump/${ORACLE_SID}_${dia}.log >> $log
  fi
}
 
verifica_tablespaces() {
  echo "Tablespaces com mais de 80% de espaço ocupado =>" >> $log
  sqlplus -S / <<-EOF_VERIFICA_TABLESPACES
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/verifica_tablespaces.log
    SELECT
      u.tablespace_name || ' com ' ||
        TO_CHAR( 100 * u.utilizado / m.maximo , '999.9') || '% ocupado' tablespace
      FROM
        (SELECT tablespace_name, SUM (bytes) utilizado
          FROM dba_segments
          GROUP BY tablespace_name) u,
        (SELECT
          tablespace_name,
          SUM (bytes) alocado,
          SUM (DECODE (autoextensible, 'NO', bytes, maxbytes)) maximo
          FROM dba_data_files
          GROUP BY tablespace_name) m,
        (SELECT
          tablespace_name, SUM (bytes) livre
          FROM dba_free_space
          GROUP BY tablespace_name) l
          WHERE
            l.tablespace_name = u.tablespace_name AND
            l.tablespace_name = m.tablespace_name AND
            100 * u.utilizado / m.maximo > 80
    UNION
    SELECT
      tablespace_name || ' com ' ||
        TO_CHAR( 100 * SUM (user_bytes) / SUM (DECODE (autoextensible, 'NO', bytes, maxbytes)) , '999.9')
        || '% ocupado' tablespace
      FROM dba_temp_files
      GROUP BY tablespace_name
      HAVING 100 * SUM(user_bytes) /  SUM (DECODE (autoextensible, 'NO', bytes, maxbytes)) > 80
    ;
    SPOOL OFF
    EXIT;
EOF_VERIFICA_TABLESPACES
  cat ${SQLPATH}/verifica_tablespaces.log >> $log 2>> $log
}
 
mostra_espaco_disco() {
  echo "Espaço em disco =>" >> $log
  df -hl -t ext3 >> $log 2>> $log
  echo "" >> $log
}
 
backup_spfile() {
  echo "Copiando spfile para ${ORACLE_HOME}/dbs/init${ORACLE_SID}_backup.ora em "`date +%R:%S` >> $log
  #Só funciona se o spfile existir
  if [ -f ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora ]; then
    #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
    if [ $USER != 'oracle' ]; then
      echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
      echo "***** tente novamente com o usuário oracle do SO." >> $log
      exit 2
    fi
    echo " --Backup do spfile (precisa de privilégio sysdba ou sysoper)"
    sqlplus -S / as sysdba <<-EOF_BACKUP_SPFILE
      SET FEEDBACK OFF
      SET TRIMSPOOL ON
      SET TERMOUT OFF
      SET PAGES 0
      SET LINES 250
      SPOOL ${SQLPATH}/backup_spfile.log
      CREATE PFILE='${ORACLE_HOME}/dbs/init${ORACLE_SID}_backup.ora'
        FROM SPFILE='${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora';
      SPOOL OFF
      EXIT
EOF_BACKUP_SPFILE
    egrep --color -n -B 2 '(ORA-|SP2-)' ${SQLPATH}/backup_spfile.log >> $log 2>> $log
  else
    echo "SPFILE ${ORACLE_HOME}/dbs/spfile${ORACLE_SID}.ora não encontrado!" >> $log
  fi
}
 
shut_down() {
  echo "Backup físico off line: desligando instância em "`date +%R:%S` >> $log
  #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
  if [ $USER != 'oracle' ]; then
    echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
    echo "***** tente novamente com o usuário oracle do SO." >> $log
    exit 2
  fi
  sqlplus -S / as sysdba <<-EOF_SHUT_DOWN
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/shut_down.log
    SHUTDOWN IMMEDIATE
    SPOOL OFF
    EXIT
EOF_SHUT_DOWN
  grep --color -n -B 2 ORA- ${SQLPATH}/shut_down.log >> $log 2>> $log
  proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
  if [ -n $proc ]; then
    echo "***** Problema ao desligar a instância $ORACLE_SID" >> $log
    echo "***** Tentando realizar um shutdown abort" >> $log
    sqlplus -S / as sysdba <<-EOF_SHUT_DOWN_ABORT
      SET FEEDBACK OFF
      SET TRIMSPOOL ON
      SET TERMOUT OFF
      SET PAGES 0
      SET LINES 250
      SPOOL ${SQLPATH}/shut_down_abort.log
      SHUTDOWN ABORT
      SPOOL OFF
      EXIT
EOF_SHUT_DOWN_ABORT
    grep --color -n -B 2 ORA- ${SQLPATH}/shut_down_abort.log >> $log 2>> $log
    proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
    if [ -n $proc ]; then
      echo "***** Algum problema sério aconteceu no banco $ORACLE_SID" >> $log
      echo "***** O servidor pode estar num estado inconsistente" >> $log
      cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
      exit 2
      grep --color -n -B 2 ORA- ${SQLPATH}/shut_down_abort.log >> $log 2>> $log
    fi
  fi
  echo "" >> $log 2>> $log
}
 
copia_datafiles() {
  echo "Backup físico of line: copiando arquivos de dados em "`date +%R:%S` >> $log
  for p in ${dados[*]}; do
    scp ${p}/oradata/${ORACLE_SID}/* ${remote_dest}:${p}/oradata/${ORACLE_SID} 2>> $log
  done
}
 
start_up() {
  echo "Backup físico: ligando instância em "`date +%R:%S` >> $log
  #Só pode ser executado pelo usuário Oracle do SO. Verificação abaixo
  if [ $USER != 'oracle' ]; then
    echo "***** A operação ${operation} não é válida com o usuário $USER" >> $log
    echo "***** tente novamente com o usuário oracle do SO." >> $log
    exit 2
  fi
  sqlplus -S / as sysdba <<-EOF_START_UP
    SET FEEDBACK OFF
    SET TRIMSPOOL ON
    SET TERMOUT OFF
    SET PAGES 0
    SET LINES 250
    SPOOL ${SQLPATH}/start_up.log
    STARTUP
    SPOOL OFF
    EXIT
EOF_START_UP
  grep --color -n -B 2 ORA- ${SQLPATH}/start_up.log >> $log 2>> $log
  if [ $? -eq 0 ]; then
    echo "***** Problema ao ligar a instância $ORACLE_SID" >> $log
    cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
    exit 2
  else
    proc=`ps -ef | egrep pmon_$ORACLE_SID  | grep -v grep`
    if [ -z $proc ]; then
      echo "***** Problema ao ligar a instância $ORACLE_SID" >> $log
      cat $log | mail -s "URGENTE!!! Erro no backup off line de `uname -n`/$dia" $oracle_mail
      exit 2
    fi
  fi
  echo "" >> $log
}
 
define_mes_anterior() {
  mes=`date +%m`
  mes=$(expr $mes - 1)
  if [ $mes = 0 ]; then
    ano=`date +%Y`
    ano=$(expr $ano - 1)
    mes=${ano}-12
  else
    mes=`date +%Y`-$mes
  fi
}
 
move_logs() {
  echo "Logs: Movendo logs em adump para adump/old/${ORACLE_SID}_audit_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/adump
  touch ${ORACLE_SID}_audit_${mes}.tar $log 2>> $log
  find -name "ora_*.aud" -exec tar -rf ${ORACLE_SID}_audit_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_audit_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_audit_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_audit_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ora_*.aud
  else
    rm ${ORACLE_SID}_audit_${mes}.tar  >> $log 2>> $log
  fi
 
  echo "Logs: Movendo logs em bdump para bdump/old/${ORACLE_SID}_bdump_log_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/bdump
  touch ${ORACLE_SID}_bdump_log_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_${mes}-*.log" -exec \
    tar -rf ${ORACLE_SID}_bdump_log_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_bdump_log_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_bdump_log_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_bdump_log_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_${mes}-*.log
  else
    rm ${ORACLE_SID}_bdump_log_${mes}.tar >> $log 2>> $log
  fi
 
  echo "Logs: Movendo trace em bdump para bdump/old/${ORACLE_SID}_bdump_trace_${mes}.tar.bz2"` >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/bdump
  touch ${ORACLE_SID}_bdump_trace_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_*.trc" -exec tar -rf ${ORACLE_SID}_bdump_trace_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_bdump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_bdump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_bdump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_*.trc
  else
    rm ${ORACLE_SID}_bdump_trace_${mes}.tar >> $log 2>> $log
  fi
 
  echo "Logs: Movendo trace em cdump para cdump/old/${ORACLE_SID}_cdump_trace_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/cdump
  touch ${ORACLE_SID}_cdump_trace_${mes}.tar $log 2>> $log
  find -name "core_*" -exec tar -rf ${ORACLE_SID}_cdump_trace_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_cdump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_cdump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_cdump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm -R core_*
  else
    rm ${ORACLE_SID}_cdump_trace_${mes}.tar >> $log 2>> $log
  fi
 
  echo "Logs: Movendo trace em udump para udump/old/${ORACLE_SID}_udump_trace_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/udump
  touch ${ORACLE_SID}_udump_trace_${mes}.tar $log 2>> $log
  find -name "${ORACLE_SID}_*.trc" -exec tar -rf ${ORACLE_SID}_udump_trace_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_udump_trace_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_udump_trace_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_udump_trace_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_*.trc
  else
    rm ${ORACLE_SID}_udump_trace_${mes}.tar >> $log
  fi
 
  echo "Logs: Movendo logs de backup para backup/old/${ORACLE_SID}_backup_${mes}.tar.bz2" >> $log
  cd /u01/app/oracle/admin/${ORACLE_SID}/backup
  touch ${ORACLE_SID}_udump_trace_${mes}.tar $log 2>> $log
  find -name "*_${mes}.log" -exec tar -rf ${ORACLE_SID}_backup_log_${mes}.tar \{\} \; 2>> $log
  if [ -s ${ORACLE_SID}_backup_log_${mes}.tar ]; then
    bzip2 ${ORACLE_SID}_backup_log_${mes}.tar  >> $log 2>> $log
    mv ${ORACLE_SID}_backup_log_${mes}.tar.bz2 old  >> $log 2>> $log
    rm ${ORACLE_SID}_${mes}-*.log
  else
    rm ${ORACLE_SID}_backup_log_${mes}.tar >> $log 2>> $log
  fi
}
 
#Rotina principal
case $operation in
  'copia_archives')
    copia_archives
    verifica_discos
  ;;
  'backup_noturno')
    echo "" >> $log 2>> $log
    echo "Inicio da rotina de backup noturno em $ORACLE_SID em "`uname -n`" para o dia ${dia}" >> $log
    echo "================================================================="  >> $log
    echo "" >> $log
    analize
    backup_logico
    verifica_data_file
    backup_fisico_on_line
    compara_backup_fisico
    backup_control_file
    backup_dbs
    limpa_archives
    verifica_alert
    verifica_tablespaces
    mostra_espaco_disco
    echo "Fim do backup noturno. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log do backup noturno de `uname -n`/${dia}" $oracle_mail
  ;;
  'backup_off_line')
    echo "" >> $log
    echo "Início do backup off line de $ORACLE_SID em "`uname -n`" para o dia ${dia}" >> $log
    echo "=============================================================================="  >> $log
    echo "" >> $log
    shut_down
    copia_datafiles
    start_up
    echo "Fim do backup off line. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log do backup off line de `uname -n`/${dia}" $oracle_mail
  ;;
  'rotina_mensal')
    define_mes_anterior
    echo "" >> $log
    echo "Início da rotina mensal de $ORACLE_SID em "`uname -n`" para o mês ${mes} em ${dia}" >> $log
    echo "=============================================================================="  >> $log
    echo "" >> $log
    move_logs
    verifica_espaco_disco
    echo "Fim da rotina mensal. Este log está disponível em $log" >> $log
    cat $log | mail -s "Log da rotina mensal de `uname -n`/${dia}" $oracle_mail
  ;;
  *)
    echo "***** A operação ${operation} não é válida" >> $log
    echo "***** chamada $0 $* ilegal"
    echo "***** uso: $0  " >> $log
  ;;
esac

Referências

PostgreSQL, discos & Cia

ou…

Tudo que você sempre quis saber sobre discos em servidores PostgreSQL e tinha vergonha de perguntar

Este é um texto que eu tenho vontade de escrever já faz bem um ano. Não escrevi antes por preguiça (é um texto longo) e porque é um texto um tanto pretensioso (tive receio de falar bobagem). Esta semana eu resolvi correr o risco. Já fazia um tempo que eu não me debruçava sobre um texto técnico um pouco mais longo, então tomei coragem e coloquei as idéias no papel, ou melhor, no blog. Muitos DBAs experientes sentirão que eu posso ter escorregado ou simplificado demais aqui ou ali. O propósito era escrever algo didático e não um livro inteiro sobre o assunto. Mas se você encontrar imprecisões técnicas ou tiver alguma sugestão para melhorar/corrigir o texto, por favor deixe um comentário.

Todo DBA é ou deveria ser tarado por discos. A não ser que você seja um daqueles que acreditam que um banco de dados possa conviver inteiro na memória sem nenhum problema (já ouviram falar de um SGDB escrito em Java que é mais rápido que o MySQL e o PostgreSQL?) você verá que os discos são o ponto chave no desempenho, na segurança e no custo do hardware. Neste texto vamos abordar alguns aspectos importantes e tentar visualizar como aplicar um pouco disso com exemplos práticos no final. Vejamos os tópicos a serem abordados:

  • RAID
  • Discos
  • Controladoras de Discos
  • Tipos de Arquivos
  • Particionamento
  • Como distribuir as partições nos discos existentes

RAID

Em termos de desempenho o mantra sempre foi “quanto mais discos melhor”. Mas algo mudou no meio do caminho. Há tempos atrás as pessoas ficavam fazendo uma ginastica danada para distribuir os tablespaces em discos diferentes. O resultado era a paralelização no acesso ao disco. Se realizado com sucesso, o processo iria dobrar a velocidade quando uma operação fosse realizada em dois discos ao mesmo tempo. Fazer isso não é simples. Uma formula mágica muito divulgada era o de separar os índices das tabelas. Como é comum acessar uma tabela e acessar seus índices também, isto parecia fazer muito sentido. Surpresa, não é bem assim que as coisas funcionam. Você tem que fazer uma avaliação real de quais objetos (tabelas e índices) são acessados mais concomitantemente. Isso era o que se chama de “evitar a contenção de discos”. Ocorre que o otimizador ao fazer uma consulta que envolve várias tabelas pode realizar o acesso a disco de diversas formas diferentes. De acordo com a época do ano, a freqüência no acesso aos objetos pode mudar, enfim, são inúmeros detalhes para serem avaliados. Resultado: distribuir os objetos em dois discos ao invés de um não significa ter o dobro de velocidade o tempo todo.

O uso massivo do RAID começou a trazer uma nova abordagem. Quanto mais discos você colocar no RAID, mais rápido o acesso será para todas as operações. Então se você dobra o número de discos no RAID, você dobra a velocidade em todo o acesso aos objetos armazenados naqueles discos. Então a questão fundamental é em quantos discos a informação vai ser dividida para gravarmos ela simultaneamente. É aqui que começa a guerra dos tipos de RAID a se utilizar.

Com o RAID 0, você tem o aproveitamento máximo dos discos. A implementação é simples e o ganho de desempenho é máximo também: o ganho de desempenho é exatamente igual ao número de discos utilizados. 2 discos, 2 vezes mais rápido. 5 discos, 5 vezes mais rápido, 100 discos, 100 vezes mais rápido. Não é maravilhoso? Simples, barato e eficiente. Só tem um problema. Se um único disco falhar… todos os seus dados em todos os discos do RAID vão para o espaço, junto com o seu emprego. Resultado, o RAID 0 só pode ser utilizado em um servidor de banco de dados em uma situação: dados temporários cuja perda não causa perda de dados nem indisponibilidade no sistema. Há um bom exemplo disso. Se você utiliza sistemas que fazem consultas muito complexas, numa base grande (vejamos, pelo menos uns 500GB é algo de tamanho considerável) como num data warehouse, você terá um volume de dados temporários considerável. Neste caso, vale a pena ter um RAID separado só para os tablespaces temporários. O PostgreSQL 8.3 traz a capacidade de indicar um lugar específico para os dados temporários. Aqui é o lugar para isso.

Então vem o nosso amigo RAID 5, que é muito rápido para leitura, mas é considerado lento para gravação. Se você tem um grande volume de dados estáticos, com muita leitura e pouca gravação, o RAID 5 pode ser para você. É verdade que o RAID 5 tem desempenho inferior em gravação. Mas se você colocar um volume grande de discos, com pelo menos 5 discos, este custo passa a ser compensado pelo aumento no número de discos. Existem também implementações do RAID 5 em hardwares proprietários que não apresentam uma penalização de gravação tão alta quanto se divulga por aí. É claro que isto depende do uso de uma ótima controladora de discos. Mas o fato é que o RAID 5 tem má fama devido ao seu problema com a segurança. Enquanto no RAID 0 você não tem segurança nenhuma, o RAID 5 permite que você perca até um disco. O problema é que se você comprar vários discos num mesmo lote, existe uma grande chance deles apresentarem defeito em no mesmo período. Se você observar dezenas de lâmpadas trocadas ao mesmo tempo, verá que elas começam a queimar na mesma época. Se isto ocorrer com seu RAID 5, você terá problemas. Então, se você se preocupa com segurança, não use RAID 5. No RAID 5 você precisa ter no mínimo 3 discos, mas você não deveria jamais montar um RAID 5 com 3 discos. Por outro lado, se você se preocupa com a segurança, colocar um número muito grande de discos aumenta a chance de haver uma falha em mais de um disco. Outro detalhe bizarro é que se ocorrer uma falha e você tiver um hot spare, este entrará em operação e começará a remontar todo o esquema de redundância novamente. Essa operação de reconstrução da paridade do RAID 5 é pesada e lenta, então se o seus discos forem do mesmo lote, a chance de um segundo disco quebrar durante a reconstrução é grande. Se isso ocorrer, você perderá todos os seus dados. Se você se preocupa com desempenho só use RAID 5 com pelo menos 5 discos. Se você se preocupa com a segurança, use um hot spare e também não aumente muito o número de discos.

Então porquê todos usam tanto o RAID 5? É simples… ele é muito mais barato que o RAID 1. Destes discos, o espaço total de armazenamento será equivalente ao espaço de todos os discos juntos menos 1. Então se você tem 10 discos de 300 GB, o espaço útil é de 3TB – 300GB = 2.7TB. Nada mau, não? Mas veja bem… a quantidade de discos tem influência enorme não apenas no custo, mas na segurança e no desempenho também. Então onde posso usar o RAID 5? Se você se preocupa exclusivamente com o custo, o RAID 5 é uma solução barata em termos de capacidade de armazenamento, combinando uma segurança mínima que diminui conforme o número de discos aumenta. Se você pensa em desempenho e tem dados atualizados com pouca freqüência, como em dados históricos, o RAID 5 é uma boa solução. Mas se você se preocupa com segurança, evite o RAID 5 e só use para armazenar dados não críticos.

Existe também o RAID 6 que começou a ser utilizado recentemente. Ele é muito semelhante ao RAID 5, mas permite a perda de até 2 discos sem interrupção no funcionamento. É mais seguro sem ser muito mais caro. Você provavelmente só vai encontrar o RAID 6 em controladoras mais sofisticadas e storages externos. Num RAID 6, com 10 discos de 300GB o espaço útil é de 2.4TB. Para um número pequeno de discos (o mínimo são 4 discos, mas você deveria pensar e começar com 6) o uso de um disco a mais para a paridade é significativo, mas para um número grande isto se torna uma questão menor. Em termos de segurança, poder perder 2 discos é muito interessante. O RAID 6 não sofre tanto com o problema da reconstrução da paridade como no RAID 5, o que aumenta bem a sua segurança. Em termos de desempenho ele é semelhante ao RAID 6.

O nosso amigo RAID 1 é o mais simples e o mais caro tipo de RAID. O ganho de desempenho dele é nulo na gravação e mas dobra a velocidade na leitura. Além disso a capacidade total de armazenamento é metade da soma dos discos. O RAID 1 é o simples espelhamento dos discos. Vejamos como as coisas ficam. Se você tem dois discos de 300GB em RAID 1, o seu espaço útil é de 300GB. Simples assim. Se você tem apenas 2 discos e não quer se arriscar com o RAID 0, o RAID 1 é sua única opção.

O tipo de RAID que fez as pessoas largarem mão de distribuir os dados em diferentes discos isolados (sem RAID), foi o RAID 10, ou RAID 1 + 0. O RAID 10 combina o aumento de segurança do RAID 1 com o aumento de desempenho do RAID 0. Só tem um problema, assim como o RAID 1, ele precisa de 50% dos discos para o espelhamento, o que encarece a solução. Outro detalhe, é que você começa a brincar de RAID 10 a partir de 4 discos e daí para frente sempre em números pares como 4, 6, 8, 10, 12, etc. Com dois discos você tem apenas o RAID 1. Assim, o único problema do RAID 10 é o custo. Imagine que com 4 discos de 300GB, você só aproveitará 600GB. Com 10 discos de 300GB, só aproveitará 1,5TB. É bem possível também que com 10 discos em RAID 5 ou 6 você tenha um desempenho de gravação semelhante ou superior e um desempenho em leitura muito maior. Então a questão do RAID 10 é realmente a segurança.

Então fica a questão: quando eu devo usar o RAID? Resposta: SEMPRE, escolhendo o RAID 10, 1, 5 ou 6 dependendo das suas prioridades e RAID 0 para casos muito especiais como um esquema complementar. A cultura que está se formando em tornos dos DBAs hoje é a de usar RAID 1 ou 10 para tudo, uma vez que a segurança raramente é uma questão menor e o custo $/GB estar caindo, particularmente com os discos SAS em substituição aos SCSI.

Discos

Falando em tipos de discos, outra coisa que você deve lembrar é que existem no mercado 3 tipos de interfaces para discos: fibre channel, SAS e SCSI. Não exite SATA, esqueça que eles existem mesmo em RAID. Não importa o que você leu no blog do beltrano, SATA é muito mais lento e muito menos confiável. Mesmo os discos SAS estão ainda sob vigilância, uma vez que sempre que o preço dos discos cai muito, a desconfiança aumenta. De qualquer forma, os discos SAS devem dominar o mercado rapidamente. Os discos fibre channel são usados apenas em storages externos de alto desempenho. É comum ver storages que suportem discos SCSI, fibre channel, SAS e SATA. Mesmo que o seu storage seja caríssimo, o fato dele suportar os discos SATA não significa que eles sejam adequados para bancos de dados. Pode ser que para servidores de arquivo o seu uso junto com RAID seja aceitável, para bancos de dados não. Você realmente vai ter que comprar uma controladora descente e discos dedicados a servidores e não a desktops.

Sobre o tamanho dos discos, há outro detalhe importante. Pelo menos na tradição dos discos SCSI, os discos de maior capacidade são os que tem o custo de $/GB melhor e o pior desempenho. Não sei se a mesma tendência se repetirá com os discos SAS, mas é bom ficar de olho. Mesmo porquê, se você precisa de muito espaço em disco, é claro que a melhor solução é ter muitos discos pequenos e não poucos discos enormes. Aumentar o número de discos é sinônimo de aumentar o desempenho. Não existem servidores de bancos de dados sérios com 1 disco. Comece com 2 discos e aumente este número aos pares. Isto o deixa na posição de começar com um RAID 1 que é uma solução aceitável para um servidor pequeno e crescer para 4 ou 6 no futuro com um RAID 10. É claro que se você não utiliza um storage externo, o gabinete do servidor vai limitá-lo seriamente. Então evite os servidores 1U (estou falando da altura do servidor no rack, é claro) que só comportam cerca de 2 discos e prefira os servidores com 2U que comportam em geral até 6 discos ou 4U que comportam cerca de 15 discos. Existem discos novos com tamanho de 2,5 polegadas ao invés das tradicionais 3,5 polegadas. Estes devem possibilitar um aumento no número de discos num mesmo gabinete além de diminuir o consumo de energia. Ainda é muito cedo para fazer uma comparação séria.

A estatística que realmente interessa para o desempenho do banco de dados é o número de operações por segundo, o IOPS e a taxa de transferência sustentada. O IOPS depende não apenas dos discos, mas da controladora e do SO utilizado. Você pode verificar o IOPS do seu servidor no Linux através do iostat. A coluna “tps” do relatório do iostat é equivalente ao IOPS do seu disco. A taxa de transferência sustentada é a quantidade de bytes que o disco consegue transferir por um longo período. Os fabricantes costumam publicar nas suas especificações a taxa de transferência e a taxa de transferência sustentada. Você deve se preocupar apenas com a segunda. É aqui que os HDs SATA perdem e muito, pois o protocolo utilizado pelo HD SATA não consegue manter uma taxa de transferência razoável. Já os discos Fibre Channel, SCSI e SAS (lembre-se que o SAS nada mais é do que o protocolo SCSI com uma interface serial).

Ao comparar os últimos lançamentos dos discos da Seagate por exemplo, vemos o disco Savvio de 2.5 polegadas, 15Krpm com interface SAS e capacidade de 36GB e 72GB. Já em 3.5 polegadas temos o Cheetah um disco de 15,6Krpm com interface SAS ou Fibre Channel e capacidade de 146GB, 300GB ou 450GB. Vejamos alguns detalhes das especificações:

Especificação 2,5″ SAS
73GB
3,5″ SAS
146GB
3,5″ FC
146GB
Taxa de transferência
externa (MB/s)
300 300 400

Taxa de transferência
sustentada interna(MB/s)

79 a 112 110 a 178 110 a 178
Latência média (ms) 2 2 2
Tempo de busca médio
Leitura/Gravação (ms)
2.9/3.3 3.4/3.9 3.4/3.9
Tempo de busca trilha a trilha
Leitura/Gravação (ms)
0,2/0,4 0,2/0,4 0,2/0,4
Potência media (W) 7,9 14,4 15,0

Notamos que:

  • A taxa de transferência externa do Fibre Channel é maior que o SAS;
  • A taxa de transferência sustentada é menor nos discos de 2.5 polegadas. Vale a pena lembrar que quanto maior o diâmetro do disco, maior a quantidade de setores nas trilhas externas do disco. Assim, mantendo o número de rotações do disco, os discos com maior diâmetro conseguem transferir um número maior de dados;
  • O tempo de busca que mede a velocidade com a qual o cabeçote se move (de trilha para trilha) é igual, mas como o disco de 3,5 polegadas tem que se movimentar por um disco com maior diâmetro, o tempo médio de busca dele é maior.
  • O consumo de energia dos discos de 2,5 é substancialmente menor, devido ao menor peso dos discos;

O custo de cada um destes discos, está entre 400 e 600 dólares. Acredite ou não, este é um preço muito razoável. Não faz nem 2 anos e tive que comprar discos de 146GB em Fibre Channel e 10Krpm por nada menos que R$ 15.000,00 cada um. Então, considerando que estamos olhando para um hardware de ponta, podemos esperar que em 2 anos estes discos se tornar opções standard.

Controladoras de discos

Bom, para encerrar a questão do hardware, você tem que pensar com cuidado na sua controladora de discos. Assim como quem vê processador não vê chipset, quem vê discos, não vê controladora de discos. Não adianta ter vários discos de 15Krpm SAS e uma controladora standard. Uma boa controladora faz toda a diferença. Há quem diga que com uma controladora ruim, vale mais a pena utilizar RAID por software do que aproveitar o RAID nativo da controladora. Além disso, a quantidade de discos que a controladora suporta, as modalidades de RAID, a quantidade de buffer cache disponível, a presença de bateria, tudo isso influencia muito. Uma controladora mais simples pode ter seu preço em torno dos 250 dólares e uma mais poderosa pode ultrapassar os 1000. Mas você deve reservar uma parte do orçamento para alguns acessórios para a sua controladora como cabos, pentes de memória e baterias externas que podem fazer você chegar facilmente aos 2 mil dólares.

Apesar de haverem controladoras que suportam até 128 discos SAS no mercado, pode ser que alocar esta quantidade de discos dentro do seu servidor não seja tão simples. Se você chegar neste ponto, pode ser interessante pensar num storage externo. Há diversos modelos de storage, escaláveis para quantidades consideráveis de discos. Você pode começar com uma gaveta contendo uma dezena de discos e ir adicionando novas gavetas e até mesmo racks chegando aos milhares de discos. Há outras vantagens consideráveis no uso de um storage externo. Você pode compartilhar o mesmo storage com mais de um servidor e montar uma SAN (Storage Area Network), o que pode ser muito interessante, para migrar dados de produção para teste, usar replicação ou até técnicas de cluster. A performance também é um fator fundamental. Eles chegam a ter vários GB de cache e boas baterias internas, o que lhe permite utilizar o cache de gravação com segurança. Além disso, os storages costumam vender alguns softwares (proprietários até a alma) que ativam capacidades especiais do hardware como tuning de discos, monitoramento avançado e o meu preferido: snapshots! O custos de soluções de médio porte de storage despencaram. Acredite ou não, já é possível contar com uma estrutura de storage completa com menos de R$ 50 mil. Vale a pena ressaltar, que para bancos de dados, os storages iSCSI embora mais baratos, não são recomendados, pois até o momento apresentam um desempenho inferior ao fibre channel. Acha muito? Você não tem idéia de o quanto os preços já caíram. Não faz muito tempo que um storage básico com Fibre Channel e 1TB não saia por menos de uns R$200 mil. É claro que esta conta pode chegar na casa dos milhões muito rápido. É só colocar milhares de discos na conta. Você acha que utilizar milhares de discos é um exagero? Convido você a olhar os testes de performance do TPC… o teste mais simples, não usam menos de 100 discos. Realmente vale a pena olhar os testes, pois além do resultado de performance, eles detalham todos os custos de hardware e software, incluindo suporte para 3 anos.

Tipos de arquivos

Agora vem uma parte realmente importante que é entender os diferentes tipos de informação que serão gravados no seu servidor. Mesmo se você tem um pequeno servidor de banco de dados com apenas dois discos (se você só tem 1, bem… sinto muito), isso é fundamental antes de sair particionando os discos.

Vejamos como podemos classifica-los:

  • Sistema Operacional

Estamos imaginando obviamente que você está criando um servidor dedicado. Servidores de bancos de dados são serviços que gostam de exclusividade, principalmente no acesso a disco. Então, se for inevitável ter que colocar mais um serviço no mesmo servidor, que este não seja um servidor de e-mail ou arquivos. Nada que vá disputar o acesso aos discos com o banco de dados. De toda a forma a idéia é que o SO não costuma ocupar muito espaço, não é um gargalo de desempenho e não compõe uma parte crítica dos dados uma vez que ele pode sempre ser reinstalado. Claro que perder o SO, vai lhe causar um bom tempo com o servidor fora do ar até que ele seja reinstalado, portanto algum tipo de proteção deve existir, como um RAID 1, 5, 6 ou 10. Em geral, uma partição com alguns GB devem ser suficientes para todo o SO, e executáveis do SGDB. Se estiver usando Linux, não esqueça de guardar uma pequena partição para o kernel (algo como 100 ou 200 MB).

  • Swap

O Linux e outros SOs utilizam uma parte do disco para servir de memória virtual paginada em caso de falta de memória. Em tese isto nunca deve acontecer e você deve ter memória suficiente para evitar este tipo de situação na maior parte do tempo. No entanto, se acontecer o Swap deve estar lá para evitar que todos os processos se percam repentinamente. O Swap deve sempre possuir sua própria partição que em geral possui o mesmo tamanho da sua memória RAM. Se você tiver mais de 4GB, pode pensar em usar um pouco menos de isso, chegando a 50% da RAM a partir dos 8GB para cima.

  • Logs

O seu servidor gera uma série de logs sobre o que acontece no banco de dados e no servidor. A quantidade de logs gerados variam muito conforme a configuração do banco de dados e demais serviços. Em geral a configuração standard do SO é suficiente para a maioria dos casos enquanto as configurações do banco de dados devem ser estudadas caso a caso. Você deve determinar onde colocar seus logs, o que logar, quando logar, etc. Uma análise de performance num ambiente de produção pode gerar alguns GB de logs em poucos minutos. Guardar uma partição para estes logs é importante. Os logs devem ficar sob controle e não devem ocupar um espaço maior do que o previsto. É comum executar faxinas periódicas nos logs. Não esqueça de configurar os logs do PostgreSQL.

  • Tablespace padrão.

O tablespace padrão é aquele utilizado para guardar o dicionário de dados. Este tablespace é crítico. Ele ocupa pouco espaço pois só consiste nos metadados a respeito dos demais objetos do banco. Se você perder o dicionário de dados, não conseguirá acessar mais nenhum objeto do banco, tornando-o completamente inútil. Em termos de segurança, este é um tablespace que deve ser muito bem protegido. Se você tiver muita memória, provavelmente o dicionário do sistema deve estar quase sempre no buffer tornando o desempenho uma questão secundária. O problema que se encontra com freqüência é que as pessoas não criam novos tablespaces para uso dos objetos normais das aplicações. Misturar ambos não é uma boa idéia. O espaço ocupado pelo tablespace default costuma ser mínimo, se ele realmente contiver apenas o dicionário de dados. A não ser que você tenha uma quantidade muito grande de objetos, particularmente visões e funções, destinar 1GB para este tablespace costuma ser mais que o suficiente.

  • Tablespace temporário

O tablespace temporário não tem impacto em termos de segurança para as informações. As informações lá armazenadas são apenas uma área de trabalho para operações intermediárias e tabelas temporárias. Em tese, estas informações jamais precisariam ser guardadas em disco, porém operações pesadas como a ordenação de uma tabela muito grande podem exigir muito deste tablespace. Particularmente os DataWarehouse, Data Marts e relatórios pesados exigem um volume considerável em disco. O desemprenho das consultas pesadas podem fazer deste tablespace algo crítico também. Vale a pena conhecer o perfil de carga da sua aplicação para saber se vale a pena investir em uma abordagem específica para este tablespace. Por padrão o tablespace temporário fica junto com o dicionario de dados, mas você pode setar a partir da versão 8.3 do PostgreSQL o parâmetro temp_tablespaces para escolher um local diferente.

  • Outros tablespaces

As informações do banco de dados ficam armazenadas ao fim e ao cabo nos seus arquivos de dados que devem possuir seus próprios tablespaces. Um critério para dividir os tablespaces é usar um par de tablespaces para tabelas e outro para índices em cada aplicações. Apesar de não ser mais comum dividir índices e tabelas em discos distintos, isto pode lhe ajudar muito em termos administrativos, resolução e recuperação de desastres. Além disso, você pode fazer ajustes de desempenhos mais agressivos nos índices, uma vez que eles podem ser reconstruídos facilmente. No entanto, alguns objetos muito grandes podem exigir particionamento. Os benefícios do particionamento de tabelas e índices se fazem mais presentes quando colocamos cada partição em um tablespace distinto que por duas vez devem estar em discos distintos. Outra questão é o tipo de uso do tablespace de acordo com o perfil de operações SQL executadas sobre seus objetos. Vou deixar aqui classificados 5 tipos básicos:

Tablespace para OLTP: é o tablespace mais crítico em termos de desempenho e segurança. Isto ocorre pois ele sofre um grande volume de pequenas gravações concorrentes. As gravações concorrentes são o verdadeiro inferno em termos de desempenho. Por outro lado, exigem técnicas mais sofisticadas para evitar a perda de dados. Tablespaces de aplicações com forte carga OLTP devem estar em discos distintos dos demais pois precisam de atenção especial.

Tablespace para BI: as aplicações de BI são completamente diferentes. Elas sofrem em geral grandes cargas periódicas de dados e não sofrem atualizações constantes. Ao contrario da carga em OLTP, em BI temos poucos usuários simultâneos e quase nenhuma operação de gravação. O grande desafio é conseguir suportar consultas complexas que envolvem um grande volume de dados. Aqui o desempenho também é crucial, pois uma única consulta pode facilmente levar dias para se concluir. A segurança não é em geral um ponto crucial, visto que os dados podem ser reconstruídos a partir de cargas externas.

Tablespace para Web: as aplicações web tradicionais são aquelas que possuem um volume absurdo de conexões simultâneas em operações predominantemente de pequenas leituras. Devido ao grande volume de acessos que um site na web pode ter, o desempenho é novamente um fator crucial. Se por um lado o baixo número de gravações costuma minimizar a chance de perda de dados, a indisponibilidade costuma ser um problema muito sério.

Tablespace Histórico: algumas aplicações ou parte delas, carregam um volume enorme de informações históricas e quase sempre estáticas. Estes dados precisam estar on-line para fins de auditoria ou consultas esporádicas. Este é um raro caso onde o desempenho e a segurança não são tão importantes. Aqui é um dos locais onde, tomando os devidos cuidados, podemos economizar um pouco nos discos.

  • Logs de transação

Os logs de transação, no PostgreSQL, são conhecidos como WAL ou Write Ahead Log. Estes arquivos são arquivos de tamanho fixo utilizados para assegurar a segurança dos dados em caso de queda de energia. Sem eles a segurança do banco de dados seria tragicamente comprometida. Os logs são então alvo de enorme preocupação em termos de segurança contra a perda de dados e ao mesmo tempo tem uma influência enorme no desempenho. Para se ter uma idéia de como o WAL é importante, em um artigo do Indiano Jignesh Hah (veja os comentários também…) ele demonstra que numa aplicação OLTP pesada com cerca de 3000 transações por segundo, seriam necessários 25 discos para atingir o IOPS necessário para não ter uma grande degradação de performance. Se adicionarmos o espelhamento que é praticamente obrigatório nestes casos estaremos falando de 50 discos só para o WAL! Veja que como as gravações no WAL são seqüenciais, deixa-los isolados em discos vai garantir uma maior velocidade, mas isto se não houver nenhum outro acesso em paralelo naquele disco ou RAID.

  • Arquivamento dos logs de transação

O archive consiste na cópia dos logs de transação que são reciclados. Fazer um backup do WAL é considerado obrigatório em ambientes de produção. Sem ele, qualquer arquivo de dados corrompido implicaria obrigatoriamente em perda de dados. O archive junto com o backup on-line dos tablespaces permitem o uso de uma técnica avançadas para recuperações de desastres conhecida como “Point In Time Recovery”. Enquanto o WAL precisa de um pouco espaço de armazenamento, é de praxe deixar em disco algo em torno de uma semana de backups do WAL, o que pode significar vários GB em disco de acordo com o volume de atualizações que o banco sofre.

A não ser em caso de bases pequenas com alguns poucos GB, o backup físico é praticamente obrigatório. Isto significa que você tem que ter espaço em disco (local ou remoto) para armazenar uma cópia de todos os seus datafiles. As exigências de desempenho aqui vão depender da sua janela de backup. Se você estiver na graça de possuir um storage com software de snapshot, então sua vida se tornará muito mais simples aqui. Lembre-se que os backups em disco não devem jamais substituir os backups em fita. Em último caso, fique apenas com os backups em fita. Mas ter uma cópia do último backup físico em disco, pode acelerar muito o processo de recuperação de desastres.

O backup lógico não é uma estratégia recomendada para bases medias e grandes. Mesmo assim, você deve pensar em reservar um espaço em disco para os backups lógicos. O motivo é que a movimentação de dados entre as bases de produção, homologação e testes costumam ser frequentes. Seria decepcionante perceber que você não tem espaço em disco para isso. Aqui, o desempenho e a segurança não costumam ser algo fundamental.

Particionamento

É possível utilizar apenas uma partição para todo o servidor? Sim. Isto é bom? Não. Existem quatro bons motivos para você separar diferentes tipos de arquivos em diferentes partições:

  1. Segurança contra perda de dados: se você tiver os dados do seu servidor em um grupo de discos, o WAL e seus arquivamentos em outro e possuir um backup físico em algum lugar, a perda completa do grupo de discos onde os tablespaces estão não implicarão em perda de dados. Separar os tablespaces do WAL e seus archives e possuir um backup físico em algum outro lugar (em outro servidor, outro disco local, outra fita, etc) são uma política muito segura para se evitar a perda de dados e conseqüentemente a perda de emprego…
  2. Segurança contra indisponibilidade: se você tiver apenas uma partição e um erro qualquer acontecer no servidor ou mesmo numa aplicação que acessa o banco de dados, ele pode começar a exigir repentinamente um montante enorme de espaço em disco até que ele fique completamente cheio. Se você tiver uma única partição no seu servidor, você terá não apenas o seu banco de dados travado, como o seu SO também. Separando os tipos de arquivos em partições distintas, você limita drasticamente o impacto deste tipo de situação;
  3. Administração: Fica mais fácil detectar áreas que estão crescendo demais se elas estiverem guardadas em caixas separadas. Dividir os tipos de arquivos em diferentes partições permite que com um único comando no SO (um ‘df’ no caso do Linux) seja possível verificar como andam se comportando diferentes tipos de arquivos;
  4. Desempenho: Se você separar diferentes tipos de arquivos em diferentes partições, poderá utilizar diferentes sistemas de arquivos em cada um deles. Além disso, discos, controladoras e sistemas de arquivos possuem diferentes configurações que podem ajudar a aumentar o desempenho em algumas áreas críticas.

Ter tipos de arquivos diferentes em partições diferentes, nem sempre significa utilizar discos ou grupos de discos em RAID distintos. Se você tiver apenas 2 discos, não será possível fazer muita coisa. Ainda assim, separar algumas coisas como: SO, logs, tablespace padrão, outros tablespaces, WAL, archives e backups em partições distintas, costuma fazer muito sentido. Um problema com as partições é que elas tem tamanho fixo, obrigando você a prever quanto espaço será necessário para cada partição. Em geral, prever isso costuma ser um dever do DBA, mas em bases novas isto pode ser mais difícil. Em todo caso, os storages e controladoras modernas permitem o uso de LUNs que mudam de tamanho dinamicamente. Se você não tiver acesso a este tipo de tecnologia, pode usar também o LVM que funciona muito bem, apesar que causar uma pouco de perda de desempenho no acesso a disco.

Como distribuir as partições nos discos existentes

Vamos imaginar aqui diferentes números de discos no servidor e possíveis configurações que poderiam ser utilizadas. Aqui estamos fazendo um chute grosseiro, você pode mudar um pouco as configurações dos discos e partições de acordo com algumas das dicas acima entre outras coisas, inclusive por exigências contratuais ou SLA.

  • Um disco

Bom, esta é a pior situação que você pode encontrar pois não é possível montar um RAID. A sua segurança contra falhas de discos é nula e o seu desempenho também será pobre. Neste caso, você deve pelo menos adorar uma política de backups freqüentes para minimizar a possível perda de dados a qual você está sujeito. Tenha certeza de alertar sobre os riscos por escrito aos seus superiores.

Mesmo tendo apenas um disco, você deve ter ao menos ter as seguintes partições:

/boot para o kernel do linux (100MB a 200MB)

/ para o restante do SO (algo entre 5 e 10GB)

/var/log ou outro local destinado aos logs (algo entre 1 e 10 GB costumam ser valores razoáveis)

swap (o mesmo tamanho do tamanho da memória RAM)

/var/lib ou /postgres outro local destinado aos dados (cerca da metade do espaço em disco restante

/backup ou outro local para os backups lógicos e/ou físicos (o restante do espaço em disco)

  • Dois discos

A não ser que você tenha dois discos de tamanhos diferentes, use RAID 1 e mantenha o esquema de particionamento descrito acima;

  • Três discos

Se você se preocupa com disponibilidade, use um RAID 1 com dois discos e deixe o disco restante como hot spare. Se você está precisando desesperadamente de mais espaço em disco, você pode montar um RAID 1 com dois discos e utilizar o 3º disco ser RAID para guardar os seus backups

  • Quatro discos

Se a sua prioridade for segurança, você pode montar dois RAIDs 1. No primeiro RAID 1 coloque o seu SO, os logs, o WAL, o archive e os backups físicos. No segundo RAID 1 coloque os tablespaces e os backups lógicos. Voucê também pode montar um RAID 1 com 2 discos, mais um disco de hot spare e utilizar o 4º disco para guardar seus backups.

Se a sua prioridade for desempenho, coloque tudo em um RAID 10 com os 4 discos.

  • Cinco discos

Use dois RAIDs 1 ou um RAID 10 e deixe um disco de hot spare.

  • Seis discos

Use a mesma configuração de 5 discos, mas reserve um disco só para backup lógico e/ou físico

  • Sete discos

Um disco ficará para hot spare, as os 6 discos sobrando podem ser divididos em um RAID 1 com dois discos e um RAID 10 com 4 discos (opção recomendada para aumentar a segurança) ou montar um RAID 10 com 6 discos (opção recomendada para privilegiar o desempenho).

Você verá que com um maior número de discos você pode separar mais as coisas em pelo menos 3 grupos:

  • Logs de transação e archives
  • Datafiles
  • Backups

Se você tiver algo como 15 ou mais discos, poderá começar a separar tablespaces em discos diferentes, optar ocasionalmente por um RAID 5 ou 6 para arquivos menos críticos e coisas do tipo. É claro que isso vai depender do seu conhecimento da aplicação, das suas exigências de performance e segurança e é claro… do seu bolso.