mai 122012
 
yum install -y binutils compat-libstdc++-33 compat-libstdc++-33.i386 elfutils-libelf elfutils-libelf.i386 gcc gcc-c++ glibc glibc.i386 glibc-common glibc-devel glibc-devel.i386 libaio libaio.i386 libaio-devel libaio-devel.i386 libgcc libgcc.i386 libstdc++-devel make sysstat compat-libstdc++-33.i686 elfutils-libelf.i686 glibc.i686 glibc-devel.i686 libaio.i686 libaio-devel.i686 libgcc.i686
mai 102012
 

E olha que 20 minutos foi para rodar o utlrp.

Há alguns dias eu fiz um post sobre o RMAN CONVERT DATABASE, que permite que um banco de dados seja migrado para outra plataforma e arquitetura. No caso do meu teste, a migração foi de CentOS 4.8 x32-64 para Solaris 10 x32-64, ambos com Oracle Database 10.2.0.4.
Mas o tempo de parada possível para o cliente não permitia a migração desta forma, pois os servidores estão acessíveis apenas por rede, e não via Storage, e o banco possui alguns bons TB.
O Oracle Golden Gate não é uma opção para o cliente, pois ele não está disponível para sua plataforma origem (RHEL 4 PowerPC).

Quais minhas opções então?

Fui estudar melhor o RMAN CONVERT DATABASE. O comando é executado na plataforma origem, que cria um script (a ser executado na plataforma destino) e uma cópia dos DATAFILEs já convertidos para a plataforma destino, informada no comando. O meu problema é o tempo de criação destes DATAFILEs em uma área temporária (com o banco de dados origem em estado READ ONLY), mais a cópia para a nova plataforma via rede, mais a migração para ASM na plataforma destino. Fora o espaço necessário para as áreas temporárias de origem e destino, ou ter apenas a área no destino e monstar na origem como NFS.

CONVERT DATABASE NEW DATABASE 'CLIENTE' TRANSPORT SCRIPT '/home/oracle/transportscript.sql' to platform 'Solaris Operating System (x86-64)' DB_FILE_NAME_CONVERT '+DADOS/cliente/datafile/' '/stage/';

E o que faz o script gerado por este comando? Nada de complexo. Resumidamente, ele cria o controlfile, abre o banco de dados em RESETLOGs, e por fim invalida e recompila todas as Procedures.

-- The following commands will create a new control file and use it
-- to open the database.
-- Data used by Recovery Manager will be lost.
-- The contents of online logs will be lost and all backups will
-- be invalidated. Use this only if online logs are damaged.

-- After mounting the created controlfile, the following SQL
-- statement will place the database in the appropriate
-- protection mode:
--  ALTER DATABASE SET STANDBY DATABASE TO MAXIMIZE PERFORMANCE

STARTUP NOMOUNT PFILE='/u01/app/oracle/product/10.2.0/db_1/dbs/init_00naj11c_1_0.ora'

-- Create SPFILE
CREATE SPFILE FROM PFILE = '/u01/app/oracle/product/10.2.0/db_1/dbs/init_00naj11c_1_0.ora';

STARTUP FORCE NOMOUNT
CREATE CONTROLFILE REUSE SET DATABASE "CLIENTE" RESETLOGS  ARCHIVELOG
    MAXLOGFILES 16
    MAXLOGMEMBERS 3
    MAXDATAFILES 100
    MAXINSTANCES 8
    MAXLOGHISTORY 292
LOGFILE
  GROUP 1 SIZE 50M,
  GROUP 2 SIZE 50M,
  GROUP 3 SIZE 50M,
  GROUP 4 SIZE 100M
DATAFILE
  '/stage/system.256.782246323',
  '/stage/undotbs1.258.782246325',
  '/stage/sysaux.257.782246325',
  '/stage/users.259.782246325',
  '/stage/example.265.782246405',
  '/stage/users.267.782246635',
  '/stage/users.269.782246711',
  '/stage/users.270.782246711',
  '/stage/users.271.782246713',
  '/stage/users.272.782246713',
  '/stage/users.273.782246713',
  '/stage/users.274.782246713',
  '/stage/users.275.782246721',
  '/stage/users.276.782246721',
  '/stage/users.277.782246721',
  '/stage/users.278.782246723'
CHARACTER SET WE8ISO8859P1
;

-- Database can now be opened zeroing the online logs.
ALTER DATABASE OPEN RESETLOGS;

-- Commands to add tempfiles to temporary tablespaces.
-- Online tempfiles have complete space information.
-- Other tempfiles may require adjustment.
ALTER TABLESPACE TEMP ADD TEMPFILE
     SIZE 20971520  AUTOEXTEND ON NEXT 655360  MAXSIZE 32767M;
-- End of tempfile additions.
--

set echo off
prompt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prompt * Your database has been created successfully!
prompt * There are many things to think about for the new database. Here
prompt * is a checklist to help you stay on track:
prompt * 1. You may want to redefine the location of the directory objects.
prompt * 2. You may want to change the internal database identifier (DBID)
prompt *    or the global database name for this database. Use the
prompt *    NEWDBID Utility (nid).
prompt ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

SHUTDOWN IMMEDIATE
STARTUP UPGRADE
@@ ?/rdbms/admin/utlirp.sql
SHUTDOWN IMMEDIATE
STARTUP
-- The following step will recompile all PL/SQL modules.
-- It may take serveral hours to complete.
@@ ?/rdbms/admin/utlrp.sql
set feedback 6;

Para agilizar a migração, minha idéia era a de migrar o banco, mas continuar aplicando ARCHIVEs na nova plataforma, que foram gerados na antiga plataforma. Mas o script criado pelo RMAN CONVERT DATABASE não permitiria isso, pois abre o banco em RESETLOGs, criando uma nova incarnação do banco de dados, inviabilizando a aplicação de ARCHIVEs da incarnação antiga.

Tentei também aplicar os ARCHIVEs antes do OPEN RESETLOGs, mas recebi um ORA-00600 informando que não era possível executar o RECOVER em um DATAFILE de UNDO. Esta pista é importante, veja mais a seguir.

Pesquisando mais a respeito, encontrei esta nota no MOS (My Oracle Support) a respeito da migração entre plataformas com o mesmo endian (meu caso). Vejam o que ela diz:

Cross-Platform Database Migration (across same endian) using RMAN Transportable Database [ID 1401921.1]
It's default behavior is to perform datafile conversion on all datafiles in the database. However, only datafiles that contain undo data require conversion including all datafiles beloging to SYSTEM tablespace and all UNDO tablespaces.

O comando CONVERT DATABASE não faz ABSOLUTAMENTE NADA nos DATAFILEs de dados! Só é necessário converter os DATAFILEs das TABLESPACEs SYSTEM e UNDO, e não o banco todo. E a TABLESPACE SYSTEM só sofrerá conversão nos segmentos de ROLLBACK, que não são utilizados, pois estou utilizando UNDO_MANAGEMENT=AUTO.

Partindo desta premissa e de acordo com a nota, considerei que um RESTORE de RMAN normal funcionaria, e após o RESTORE, executar o CONVERT DATAFILE apenas no que é necessário, e em seguida executar RECOVER, aplicando ARCHIVEs até o dia da migração, onde só então executo o OPEN RESETLOGs após aplicar o último ARCHIVE. O CONTROLFILE posso recuperar facilmente com um RESTORE CONTROLFILE FROM, também via RMAN..

Então o procedimento é o seguinte:
– Servidor VELHO: Cria PFILE e copia para Servidor NOVO;
– Servidor NOVO: Adapta diretórios do PFILE, se necessário. Se caminhos mudaram, adicione parâmetros DB_FILE_NAME_CONVERT e LOG_FILE_NAME_CONVERT;
ALTER SYSTEM SET DB_FILE_NAME_CONVERT=’+DADOS’,'+CLIENTE’ SCOPE=SPFILE;
ALTER SYSTEM SET LOG_FILE_NAME_CONVERT=’+FRA’,'+CLIENTE’ SCOPE=SPFILE;
– Servidor NOVO: Inicia em NOMOUNT;
– Servidor VELHO: Cria BACKUP do CONTROLFILE por RMAN, copia o BACKUPPIECE para Servidor NOVO (BACKUP CURRENT CONTROLFILE);
– Servidor NOVO: Restaura o CONTROLFILE pelo RMAN (RESTORE CONTROLFILE FROM ‘/stage/o1_mf_ncnnf_TAG20120510T030757_7tppsy3n_.bkp’;);
– Servidor NOVO: Passa a instância para o estado MOUNT;
– Servidor VELHO: Executa BACKUPSET quente via RMAN, e copia para Servidor NOVO;
– Servidor NOVO: Executa CATALOG nos BACKUPSETs copiados via RMAN;
– Servidor NOVO: Executa RESTORE DATABASE via RMAN:
RMAN> {
RESTORE DATABASE;
SWITCH DATAFILE ALL;
SWITCH TEMPFILE ALL;
}
– Servidor VELHO: Verificar quais DATAFILEs tem segmentos de UNDO:
SQL> SELECT FILE_ID “Datafiles requiring Conversion” FROM DBA_DATA_FILES WHERE TABLESPACE_NAME IN (SELECT DISTINCT TABLESPACE_NAME FROM DBA_ROLLBACK_SEGS);
– Servidor NOVO: Verificar nomes dos DATAFILEs informados no passo anterior:
SQL> SELECT NAME “Datafiles requiring Conversion” FROM V$DATAFILE WHERE FILE# IN (1,2);
– Servidor NOVO: Executa CONVERT em todos DATAFILEs com segmentos de UNDO:
RMAN> CONVERT DATAFILE ‘+CLIENTE/cliente/datafile/system.260.782918365′ FROM PLATFORM ‘Linux x86 64-bit’;
RMAN> CONVERT DATAFILE ‘+CLIENTE/cliente/datafile/undotbs1.274.782918689′ FROM PLATFORM ‘Linux x86 64-bit’;
– Servidor VELHO: Copia Archives para Servidor NOVO;
– Servidor NOVO: Executa CATALOG nos Archives copiados;
– Servidor NOVO: Executa RECOVER DATABASE;

Continuo executando uma atualização periodicamente até o dia da migração, dependendo do volume de ARCHIVEs gerados:
– Servidor VELHO: Copia Archives para Servidor NOVO;
– Servidor NOVO: Executa CATALOG nos Archives copiados;
– Servidor NOVO: Executa RECOVER DATABASE;

E no dia da migração:
– Servidor VELHO: Cria o último Archive: ALTER SYSTEM ARCHIVE LOG CURRENT;
– Servidor VELHO: Copia Archives para Servidor NOVO;
– Servidor NOVO: Executa CATALOG nos Archives copiados via RMAN;
– Servidor NOVO: Executa RECOVER DATABASE;
– Servidor NOVO: Abre o banco: ALTER DATABASE OPEN RESETLOGS;
– Servidor NOVO: Adiciona TEMPFILEs: ALTER TABLESPACE TEMP ADD TEMPFILE SIZE 20971520 AUTOEXTEND ON NEXT 655360 MAXSIZE 32767M;
– Servidor NOVO: SHUTDOWN IMMEDIATE;
– Servidor NOVO: STARTUP UPGRADE;
– Servidor NOVO: Invalidar todas as Procedures: @?/rdbms/admin/utlirp.sql;
– Servidor NOVO: SHUTDOWN IMMEDIATE;
– Servidor NOVO: STARTUP;
– Servidor NOVO: Recompilar todas as procedures: @?/rdbms/admin/utlrp.sql;

Para facilitar e agilizar ainda mais o processo, eu poderia até montar a FRA origem como NFS no destino, mas não foi necessário.
Teoricamente, eu poderia criar até um Data Guard Physical Standby na nova arquitetura, mas eu preferi evitar ao máximo procedimentos não homologados pela Oracle, que podem custar o suporte ao produto.

Não coloquei o teste todo aqui, porque no final foi praticamente um RESTORE / RECOVER normal, como se fosse em outro servidor mas da mesma plataforma. Mas quis compartilhar o planejamento aqui com vocês (e para mim também, mês que vem já terei esquecido como se fazia isso).

mai 102012
 

No exemplo abaixo eu crio 10 arquivos de 1GB cada, para utilizar como discos para o ASM, para testes.

dd if=/dev/zero of=/asmdisks/_file_disk1 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk2 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk3 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk4 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk5 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk6 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk7 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk8 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk9 bs=1k count=1000000
dd if=/dev/zero of=/asmdisks/_file_disk10 bs=1k count=1000000

lofiadm -a /asmdisks/_file_disk1
lofiadm -a /asmdisks/_file_disk2
lofiadm -a /asmdisks/_file_disk3
lofiadm -a /asmdisks/_file_disk4
lofiadm -a /asmdisks/_file_disk5
lofiadm -a /asmdisks/_file_disk6
lofiadm -a /asmdisks/_file_disk7
lofiadm -a /asmdisks/_file_disk8
lofiadm -a /asmdisks/_file_disk9
lofiadm -a /asmdisks/_file_disk10

ls -lL /dev/lofi/*

mknod /asmdisks/vdisk1 c 144 1
mknod /asmdisks/vdisk2 c 144 2
mknod /asmdisks/vdisk3 c 144 3
mknod /asmdisks/vdisk4 c 144 4
mknod /asmdisks/vdisk5 c 144 5
mknod /asmdisks/vdisk6 c 144 6
mknod /asmdisks/vdisk7 c 144 7
mknod /asmdisks/vdisk8 c 144 8
mknod /asmdisks/vdisk9 c 144 9
mknod /asmdisks/vdisk10 c 144 10

chown oracle:dba /asmdisks/vdisk1
chown oracle:dba /asmdisks/vdisk2
chown oracle:dba /asmdisks/vdisk3
chown oracle:dba /asmdisks/vdisk4
chown oracle:dba /asmdisks/vdisk5
chown oracle:dba /asmdisks/vdisk6
chown oracle:dba /asmdisks/vdisk7
chown oracle:dba /asmdisks/vdisk8
chown oracle:dba /asmdisks/vdisk9
chown oracle:dba /asmdisks/vdisk10
mai 102012
 

Quando foi criado um Pool do ZFS? Quando tivemos problemas no espelhamento?
Toda a vida de um Pool ZFS pode ser verificada pelo comando zpool history, desde sua criação, até parâmetros alterados e manutenções executadas.
Se utilizado com um Pool como argumento do comando, retorna apenas dados deste Pool. Caso contrário, retorna de todos.

ricardo@solaris:~$ sudo zpool history test
History for 'test':
2012-05-03.08:21:07 zpool create test mirror c3t2d0 c3t3d0
2012-05-04.11:05:46 zfs set compression=on test
2012-05-04.11:08:06 zfs set compression=off test
2012-05-04.11:41:06 zfs set compression=on test
2012-05-04.11:44:10 zfs set compression=gzip-9 test
2012-05-07.05:59:36 zfs set compression=off test
2012-05-07.06:03:06 zfs set dedup=on test
2012-05-07.06:13:32 zfs set dedup=on test
2012-05-09.08:17:17 zpool scrub test
2012-05-09.08:21:47 zpool online test c3t2d0
2012-05-09.08:22:56 zpool online test c3t2d0
2012-05-09.08:23:28 zpool scrub test
2012-05-09.08:27:10 zpool detach test c3t2d0
2012-05-09.09:04:48 zpool attach test c3t3d0 c3t2d0
2012-05-09.09:53:02 zpool export test
2012-05-09.09:53:10 zpool import test
ricardo@solaris:~$ sudo zpool history oradata
History for 'oradata':
2012-05-09.14:18:55 zpool create oradata c3t4d0
ricardo@solaris:~$ sudo zpool history rpool
History for 'rpool':
2012-05-02.10:50:42 zpool create -f rpool c3t0d0s0
2012-05-02.10:50:42 zfs create -p -o mountpoint=/export rpool/export
2012-05-02.10:50:43 zfs set mountpoint=/export rpool/export
2012-05-02.10:50:43 zfs create -p rpool/export/home
2012-05-02.10:50:43 zfs create -p -V 1024m rpool/swap
2012-05-02.10:50:45 zfs set primarycache=metadata rpool/swap
2012-05-02.10:50:45 zfs create -p -V 512m rpool/dump
2012-05-02.11:28:22 zpool set bootfs=rpool/ROOT/solaris rpool
2012-05-02.11:42:22 zfs unmount rpool/ROOT/solaris
2012-05-02.13:30:09 zfs set primarycache=metadata rpool/swap
2012-05-02.13:30:12 zfs create -p rpool/export/home/ricardo
2012-05-02.13:38:04 zfs volsize=8g rpool/swap
2012-05-02.13:38:42 zfs set primarycache=metadata rpool/swap
2012-05-02.13:46:48 zfs set primarycache=metadata rpool/swap
2012-05-02.13:48:16 zfs create -V 8G rpool/swap02
2012-05-02.13:48:52 zfs set primarycache=metadata rpool/swap02
2012-05-03.08:09:00 zfs set primarycache=metadata rpool/swap
2012-05-03.08:14:16 zfs set primarycache=metadata rpool/swap
2012-05-04.07:25:42 zfs set primarycache=metadata rpool/swap
2012-05-04.08:41:03 zfs set primarycache=metadata rpool/swap
2012-05-04.11:03:35 zfs set primarycache=metadata rpool/swap
2012-05-07.05:57:30 zfs set primarycache=metadata rpool/swap
2012-05-08.11:53:31 zfs set primarycache=metadata rpool/swap
2012-05-09.07:36:34 zfs set primarycache=metadata rpool/swap
2012-05-09.07:47:16 zfs set primarycache=metadata rpool/swap
2012-05-09.08:03:48 zfs set primarycache=metadata rpool/swap
2012-05-09.09:01:05 zfs set primarycache=metadata rpool/swap
2012-05-09.10:31:33 zfs set primarycache=metadata rpool/swap
2012-05-09.11:13:24 zfs set primarycache=metadata rpool/swap
2012-05-09.14:17:49 zfs set primarycache=metadata rpool/swap

ricardo@solaris:~$
mai 092012
 

O desempenho de I/O em Pools ZFS deve ser verificado com o comando zpool iostat, e não com o iostat do Solaris.

A opção -Td imprime a data e horário da coleta.
A opção -v traz mais informações sobre cada vdev (discos) indidualmente.
O 10 no final do comando irá imprimir o resultado continuamente a cada 10 segundos, parando somente com Control+C.
O oradata é o Pool que quero monitorar. Se quiser monitorar todos, basta não informar um Pool.

ricardo@solaris:~$ zpool iostat -Td -v -l oradata 10
Wednesday, May  9, 2012 02:33:42 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.91G  97.6G      4     24   848K  3.33M
  c3t4d0    1.91G  97.6G      4     24   848K  3.33M
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:33:52 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.90G  97.6G     12     18  1.64M   630K
  c3t4d0    1.90G  97.6G     12     18  1.64M   630K
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:34:02 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.90G  97.6G      8      7  3.49M   327K
  c3t4d0    1.90G  97.6G      8      7  3.49M   327K
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:34:12 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.90G  97.6G      0     14   205K  1.36M
  c3t4d0    1.90G  97.6G      0     14   205K  1.36M
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:34:22 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.93G  97.6G      0     14  51.3K   762K
  c3t4d0    1.93G  97.6G      0     14  51.3K   762K
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:34:32 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.93G  97.6G      1      9   154K   604K
  c3t4d0    1.93G  97.6G      1      9   154K   604K
----------  -----  -----  -----  -----  -----  -----

^C
ricardo@solaris:~$ zpool iostat -Td -v -l 10
Wednesday, May  9, 2012 02:34:40 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.93G  97.6G      4     23   859K  3.17M
  c3t4d0    1.93G  97.6G      4     23   859K  3.17M
----------  -----  -----  -----  -----  -----  -----
rpool       34.6G  64.9G     47     29  1.44M  3.25M
  c3t0d0s0  34.6G  64.9G     47     29  1.44M  3.25M
----------  -----  -----  -----  -----  -----  -----
test        1.28G  8.66G      0      0    109    760
  mirror    1.28G  8.66G      0      0    109    760
    c3t3d0      -      -      0      0    744    787
    c3t2d0      -      -      0      0    669    787
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:34:50 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.95G  97.5G      3     44   500K   508K
  c3t4d0    1.95G  97.5G      3     44   500K   508K
----------  -----  -----  -----  -----  -----  -----
rpool       34.8G  64.7G     13     76  2.61M  30.9M
  c3t0d0s0  34.8G  64.7G     13     76  2.61M  30.9M
----------  -----  -----  -----  -----  -----  -----
test        1.28G  8.66G      0      0      0      0
  mirror    1.28G  8.66G      0      0      0      0
    c3t3d0      -      -      0      0      0      0
    c3t2d0      -      -      0      0      0      0
----------  -----  -----  -----  -----  -----  -----

Wednesday, May  9, 2012 02:35:00 PM BRT
               capacity     operations    bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
oradata     1.95G  97.5G     36     30  8.28M  8.33M
  c3t4d0    1.95G  97.5G     36     30  8.28M  8.33M
----------  -----  -----  -----  -----  -----  -----
rpool       34.8G  64.7G     10      0  1.25M      0
  c3t0d0s0  34.8G  64.7G     10      0  1.25M      0
----------  -----  -----  -----  -----  -----  -----
test        1.28G  8.66G      0      0      0      0
  mirror    1.28G  8.66G      0      0      0      0
    c3t3d0      -      -      0      0      0      0
    c3t2d0      -      -      0      0      0      0
----------  -----  -----  -----  -----  -----  -----

^C
ricardo@solaris:~$
mai 092012
 
projadd -U oracle -K "project.max-shm-memory=(priv,4g,deny)" user.oracle
projmod -sK "project.max-shm-memory=(priv,4g,deny)" user.oracle
projmod -sK "project.max-sem-nsems=(priv,512,deny)" user.oracle
projmod -sK "project.max-sem-ids=(priv,128,deny)" user.oracle
projmod -sK "project.max-shm-ids=(priv,128,deny)" user.oracle
projmod -sK "process.max-file-descriptor=(priv,65536,deny)" user.oracle
mai 092012
 

O ZFS possui a capacidade de self healing, ou seja, auto correção. Quando outro Volume Manager espalharia uma possível corupção de dados, ele faz o contrário.

Para testar esta capacidade no pool test, primeiro verificamos que não há erros.

ricardo@solaris:~$ sudo zpool list
Password:
NAME    SIZE  ALLOC   FREE  CAP  DEDUP  HEALTH  ALTROOT
rpool  99.5G  22.5G  77.0G  22%  1.00x  ONLINE  -
test   9.94G  1.28G  8.66G  12%  4.18x  ONLINE  -
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: ONLINE
  scan: resilvered 1.28G in 0h9m with 0 errors on Wed May  9 09:12:50 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            c3t3d0  ONLINE       0     0     0
            c3t2d0  ONLINE       0     0     0

errors: No known data errors

Agora vamos criar um arquivo extra para testes, e verificar sua integridade.

ricardo@solaris:/test$ mkfile 1g /test/ArquivoTeste
ricardo@solaris:/test$ md5sum /test/ArquivoTeste > /test/ArquivoTeste.md5
ricardo@solaris:/test$ md5sum --check /test/ArquivoTeste.md5
/test/ArquivoTeste: OK
ricardo@solaris:/test$ ls -lh /test/
total 2097435
-rw-------   1 ricardo  staff       1.0G May  9 09:49 ArquivoTeste
-rw-r--r--   1 ricardo  staff         53 May  9 09:49 ArquivoTeste.md5
drwxr-xr-x   3 ricardo  staff          3 May  7 06:13 Docs01
drwxr-xr-x   3 ricardo  staff          3 May  7 06:16 Docs02
drwxr-xr-x   3 ricardo  staff          3 May  7 06:22 Docs03
drwxr-xr-x   3 ricardo  staff          3 May  7 06:38 Docs04
ricardo@solaris:/test$ df -h /test/
Filesystem             Size   Used  Available Capacity  Mounted on
test                    15G   6.2G       8.4G    43%    /test

Agora vamos causar diversas corrupções em um dos discos, com o comando dd.
Fiz três gravações de dados aleatórios no disco, uma de 1MB, outra de 10MB, e depois uma de 100MB.

ricardo@solaris:/test$ sudo dd if=/dev/urandom of=/dev/dsk/c3t3d0 bs=1024 count=1024
Password:
1024+0 records in
1024+0 records out
ricardo@solaris:/test$ sudo dd if=/dev/urandom of=/dev/dsk/c3t3d0 bs=1024 count=10240
10240+0 records in
10240+0 records out
ricardo@solaris:/test$ sudo dd if=/dev/urandom of=/dev/dsk/c3t3d0 bs=1024 count=102400
102400+0 records in
102400+0 records out

Agora verificamos o estado do pool, e continua tudo em ordem.

ricardo@solaris:/test$ zpool status test
  pool: test
 state: ONLINE
  scan: resilvered 1.28G in 0h9m with 0 errors on Wed May  9 09:12:50 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            c3t3d0  ONLINE       0     0     0
            c3t2d0  ONLINE       0     0     0

errors: No known data errors

Como o ZFS faz um grande uso de cache em memória, acho que ele não detectou ainda a corrupção feita diretamente no disco físico. Vamos então desmontar e montar o pool, e refazer a verificação.

ricardo@solaris:/test$ sudo zpool export test
cannot unmount '/test': Device busy
ricardo@solaris:/test$ cd
ricardo@solaris:~$ sudo zpool export test
ricardo@solaris:~$ sudo zpool import test
ricardo@solaris:~$ zpool status test
  pool: test
 state: ONLINE
status: One or more devices has experienced an unrecoverable error. An attempt was made to correct the error. Applications are unaffected.
action: Determine if the device needs to be replaced, and clear the errors
        using 'zpool clear' or replace the device with 'zpool replace'.
   see: http://www.sun.com/msg/ZFS-8000-9P
  scan: resilvered 1.28G in 0h9m with 0 errors on Wed May  9 09:12:50 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            c3t3d0  ONLINE       0     0     7
            c3t2d0  ONLINE       0     0     0

errors: No known data errors

Agora sim o ZFS acusou o erro, mas como ele mesmo informa, foi feita uma tentativa de corrigir o erro, e aplicações não foram afetadas. Adicionalmente, o comando informa que deve ser melhor trocar o disco (ele não sabe que eu fiz o dd).
Conferindo a integridade do arquivo de teste, realmente ele continua ok.

ricardo@solaris:~$ ls -lh /test
total 2097435
-rw-------   1 ricardo  staff       1.0G May  9 09:49 ArquivoTeste
-rw-r--r--   1 ricardo  staff         53 May  9 09:49 ArquivoTeste.md5
drwxr-xr-x   3 ricardo  staff          3 May  7 06:13 Docs01
drwxr-xr-x   3 ricardo  staff          3 May  7 06:16 Docs02
drwxr-xr-x   3 ricardo  staff          3 May  7 06:22 Docs03
drwxr-xr-x   3 ricardo  staff          3 May  7 06:38 Docs04
ricardo@solaris:~$ md5sum --check /test/ArquivoTeste.md5
/test/ArquivoTeste: OK
ricardo@solaris:~$
mai 092012
 

Após desligar um servidor com Solaris 11 “no dedo”, várias vezes, um pool espelhado do ZFS teve um dos discos corrompido.
Como era espelhado, os dados continuaram acessíveis.
O comando zpool list mostrava o status problemático do pool.

login as: ricardo
Using keyboard-interactive authentication.
Password:
Last login: Wed May  9 08:09:44 2012 from 192.168.56.1
Oracle Corporation      SunOS 5.11      11.0    November 2011
ricardo@solaris:~$ df -h /test
Filesystem             Size   Used  Available Capacity  Mounted on
test                    14G   5.2G       8.4G    39%    /test
ricardo@solaris:~$ ls -lh /test/
total 12
drwxr-xr-x   3 ricardo  staff          3 May  7 06:13 Docs01
drwxr-xr-x   3 ricardo  staff          3 May  7 06:16 Docs02
drwxr-xr-x   3 ricardo  staff          3 May  7 06:22 Docs03
drwxr-xr-x   3 ricardo  staff          3 May  7 06:38 Docs04
ricardo@solaris:~$ sudo zpool list test
NAME   SIZE  ALLOC   FREE  CAP  DEDUP    HEALTH  ALTROOT
test  9.94G  1.28G  8.66G  12%  4.18x  DEGRADED  -

A comando zpool scrub examina todos os dados de um pool, e se possível, já corrige o problema.
O scrub continua acontecendo em background, e seu progresso (depende do tamanho do pool) pode ser conferido com o comando zpool status.

ricardo@solaris:~$ sudo zpool scrub test
ricardo@solaris:~$ sudo zpool list test
NAME   SIZE  ALLOC   FREE  CAP  DEDUP    HEALTH  ALTROOT
test  9.94G  1.28G  8.66G  12%  4.18x  DEGRADED  -
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: DEGRADED
status: One or more devices has been removed by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: scrub in progress since Wed May  9 08:16:44 2012
    357M scanned out of 1.28G at 11.9M/s, 0h1m to go
    0 repaired, 27.33% done
config:

        NAME        STATE     READ WRITE CKSUM
        test        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            c3t2d0  REMOVED      0     0     0
            c3t3d0  ONLINE       0     0     0

errors: No known data errors
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: DEGRADED
status: One or more devices has been removed by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: scrub in progress since Wed May  9 08:16:44 2012
    481M scanned out of 1.28G at 10.0M/s, 0h1m to go
    0 repaired, 36.77% done
config:

        NAME        STATE     READ WRITE CKSUM
        test        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            c3t2d0  REMOVED      0     0     0
            c3t3d0  ONLINE       0     0     0

errors: No known data errors
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: DEGRADED
status: One or more devices has been removed by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: scrub in progress since Wed May  9 08:16:44 2012
    1.27G scanned out of 1.28G at 7.14M/s, 0h0m to go
    0 repaired, 99.33% done
config:

        NAME        STATE     READ WRITE CKSUM
        test        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            c3t2d0  REMOVED      0     0     0
            c3t3d0  ONLINE       0     0     0

errors: No known data errors

Após o scrub terminar, nenhum erro foi encontrado nos dados, mas o pool continuava sem espelhamento, e o próprio comando zpool status recomendava a subistiuição do disco.

ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: DEGRADED
status: One or more devices has been removed by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: scrub repaired 0 in 0h3m with 0 errors on Wed May  9 08:20:11 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            c3t2d0  REMOVED      0     0     0
            c3t3d0  ONLINE       0     0     0

errors: No known data errors

Tentei colocar o disco em estado online, mas ele continuava com defeito.

ricardo@solaris:~$ sudo zpool online test c3t2d0
warning: device 'c3t2d0' onlined, but remains in faulted state
use 'zpool replace' to replace devices that are no longer present
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: DEGRADED
status: One or more devices has been removed by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: scrub repaired 0 in 0h3m with 0 errors on Wed May  9 08:20:11 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        DEGRADED     0     0     0
          mirror-0  DEGRADED     0     0     0
            c3t2d0  REMOVED      0     0     0
            c3t3d0  ONLINE       0     0     0

errors: No known data errors

Substituí então o disco defeituoso, e refiz o mirror. O comando zpool attach faz com que o segundo disco informado como opção seja adicionado como um espelho do primeiro, já existente e com dados.

ricardo@solaris:~$ sudo zpool detach test c3t2d0
ricardo@solaris:~$ sudo zpool status test
  pool: test
 state: ONLINE
  scan: scrub repaired 0 in 0h2m with 0 errors on Wed May  9 08:25:39 2012
config:

        NAME      STATE     READ WRITE CKSUM
        test      ONLINE       0     0     0
          c3t3d0  ONLINE       0     0     0

errors: No known data errors
ricardo@solaris:~$ sudo zpool attach test c3t3d0 c3t2d0
ricardo@solaris:~$ sudo zpool status test
Password:
  pool: test
 state: ONLINE
  scan: resilvered 1.28G in 0h9m with 0 errors on Wed May  9 09:12:50 2012
config:

        NAME        STATE     READ WRITE CKSUM
        test        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            c3t3d0  ONLINE       0     0     0
            c3t2d0  ONLINE       0     0     0

errors: No known data errors
ricardo@solaris:~$ ls -lh /test
total 12
drwxr-xr-x   3 ricardo  staff          3 May  7 06:13 Docs01
drwxr-xr-x   3 ricardo  staff          3 May  7 06:16 Docs02
drwxr-xr-x   3 ricardo  staff          3 May  7 06:22 Docs03
drwxr-xr-x   3 ricardo  staff          3 May  7 06:38 Docs04
ricardo@solaris:~$