Nesta edição iniciaremos uma série de trabalhos onde falaremos de forma abrangente e passo a passo sobre a configuração otimizada de um servidor Linux para banco de dados. Usarei como exemplo para esse artigo o PostgreSQL, mas as configurações mostradas se aplicam praticamente a qualquer servidor de banco de dados para Linux.

Particionamento e sistemas de arquivos

O Linux é um sistema operacional baseado no UNIX (Unix-like) padrão POSIX, totalmente aberto, ou seja, seu código fonte está disponível publicamente para qualquer pessoa. Isso motiva grandes empresas a atuarem como “amigos do pingüim”, a exemplo da IBM, Sun, Borland, Nokia, entre outras.

Uma de suas vantagens é possuir várias distribuições, o que permite atingir vários tipos de usuários. A principal diferença entre as distribuições são, basicamente, os programas que cada uma possui, a versão do kernel, e os módulos de instalação e de configuração do sistema operacional.

Diferente do MS-DOS, onde ficávamos restritos a utilizar a FAT como sistema de arquivos, ou do próprio Windows onde podemos optar por FAT/FAT32 e NTFS, no Linux encontramos uma ampla variedade de sistemas de arquivos, entre eles o XFS, JFS, EXT2, EXT3, ReiserFS, etc. Cada sistema de arquivo tem uma característica própria que pode influenciar diretamente na velocidade do banco de dados, uma vez que um sistema de arquivo rápido contribui e muito para a performance do SGBD.

Com o aumento de empresas que comercializam ou distribuem o Linux (RedHat, Mandrake, Conectiva, Suse, etc.), foi necessário criar um padrão de compatibilidade entre elas, chamado de LSB (saiba mais em Linux fondation). O LSB define uma série de regras a fim de estreitar as diferenças existentes entre cada distribuição. Na padronização está incluída o nome dos diretórios, arquivos de configuração, etc. O quadro 1 mostra a estrutura básica de diretórios no Linux.


/        -  Raiz do Sistema, contém as subpastas abaixo.

bin/   -  Principais binários do sistema.

boot/            -  Arquivos de Boot.

dev/   -  “Pseudo Arquivos” (ver glóssario).

etc/   -  Maioria dos arquivos de configuração.

home/ -  Pasta dos usuários com seus respectivos arquivos.

lib/     -  Principais bibliotecas do Linux.

mnt/   -  Montagem de dispositivos, para acesso ao CD-ROM, Disquetes, etc.

proc/  -  Informações do Kernel sobre o Sistema Operacional.

root/   -  Pasta “home” do Super Usuário.

sbin/   -  Principais binários de administração.

tmp/   -  Arquivos temporários.

usr/    -  Contém os binários, libs, confs, etc dos pacotes que não são padrão do LINUX.

var/    -  Logs e arquivos variados.

Otimizando um servidor Linux para banco de dados
Figura 1. Partições Linux.

No Linux não atribuímos letras as unidades, ao invés disso, vinculamos uma fatia do HD a um diretório. No exemplo mostrado na figura 1, se um arquivo fosse gravado na pasta /usr/local/database, ele estaria sendo gravado na partição de 25Gb. A figura 1 representa um HD hipotético de 40GB, dividido em várias partições. Fazendo uma analogia ao Windows, teríamos um drive C: com 5G, D: com 25Gb, E: com 500MB para Swap, e por último 10G não particionado. Sabendo disso, seguem algumas dicas:

  • Nunca criar somente uma única partição. Em um caso como esse, se acabar o espaço da partição “/”, os programas que armazenam informações no disco irão “morrer” pois não haverá espaço para salvá-las. Isto porque todas as outras pastas (ex: “/var”, ”/home”, “/usr”, “/tmp”, etc.) fariam parte da mesma partição de “/”, ou seja, todas estariam sem espaço.
  • Sempre criar o swap com no mínimo o dobro da quantidade de memória RAM disponível, especialmente em casos onde a RAM disponível é menor que 2GB. Pela naturalidade dos fatos, um servidor de BD com menos de 2GB de RAM tem grande possibilidade de usar toda a RAM disponível, dependendo obviamente do número de conexões, configurações do sistema operacional, e dos parâmetros de configuração do próprio SGBD. Um SWAP com o dobro da memória RAM garante que o servidor não ficará sem memória disponível (a swap é usada como RAM). É importante observar que não devemos usar a SWAP como alternativa de substituição da memória RAM, ou seja, não devemos ter 512Mb de RAM e uma SWAP de 4Gb para um servidor que irá utilizar 3,5Gb de RAM! A SWAP é uma memória mapeada no disco rígido, e, portanto seu acesso é sempre mais lento que o acesso a RAM. Quanto mais SWAP o servidor de BD utilizar, mais lento ele será.
  • Evitar instalar pacotes desnecessários para a instalação do servidor. Por exemplo, por que instalar os pacotes de manipulação gráfica do Linux (exceto o Oracle que necessita do ambiente gráfico para ser instalado, devido o Oracle Universal Installer - OUI) se meu servidor irá rodar o SGBD de modo dedicado? Outros pacotes que muitas vezes podem ser deixados de lado são: Servidor de DNS, Servidor de E-mail, Jogos, Multimídia, etc. Além de consumir espaço em disco e recursos do sistema, podem prejudicar a segurança do servidor, deixando-o vulnerável a ataques e crashs.
  • Durante o processo de tuning, saiba onde está mexendo e o que está fazendo. Em alguns casos, um parâmetro errado faz com que você prejudique a velocidade do banco.

Nota

Diferente do Windows, onde o swap é realizado em um arquivo (pagefile), no Linux, a área de swap é uma partição específica e marcada para esse propósito.

Durante a configuração de servidores de BD, costumo utilizar como referência a configuração mostrada na tabela 1. Vale deixar claro que não existe uma regra fixa para essas configurações. Os valores mostrados servem apenas para o leitor ter uma idéia das configurações de partições do disco de um servidor de banco de dados.

Tamanho Recomendável Aonde irá montar Sistema de Arquivo Por que isso?
1024Mb / Ext3 É tamanho suficiente para os demais diretórios e arquivos que o RedHat gera.
100Mb /boot Ext3 Local onde ficará o kernel compilado e pacotes responsáveis pelo boot.
2048Mb /usr Ext3 Nesta pasta será instalado uma série de pacotes que o Red Hat utiliza. Além do código fonte do Kernel (em /usr/src/linux).
1024Mb /var Ext2 É a pasta onde ficam os logs e arquivos “temporários” do sistema operacional. É sempre bom separar em outra partição para que não pare o servidor.
1024Mb /tmp Ext2 Este é a pasta de arquivos temporários que alguns softwares utilizam. Costumo utilizá-la para gerar ou ler arquivos, por exemplo em processos de dump. O Ext2 é muito rápido, mas nada seguro.
Depende da base. /database XFS/ReiserFs ou JFS Esses são os três sistemas de arquivos mais usados para banco de dados.
Depende da base. /database/transaction Ext2 Esses são os três sistemas de arquivos mais usados para banco de dados.
Tabela 1. Tabela base para configuração das partições para um servidor de BD.

Cada linha da tabela 1 é uma partição do disco. As pastas /database e /database/transaction merecem uma atenção especial:

  1. /database: é um nome genérico utilizado nesse artigo para designar a pasta de instalação do SGBD e do arquivo do banco de dados. Em uma situação real pode ser interessante, em termos de performance, deixar o arquivo do banco de dados em uma partição própria.
  2. Ela pode ter o nome determinado pelo próprio fabricante do banco de dados, ou especificada pelo DBA no momento de instalação. Para o PostgreSQL sugiro a instalação na pasta /usr/local/pgsql. É importante ressaltar que esta partição deve ser formatada como JFS, XFS ou ReiserFS. Veremos porque mais adiante.
  3. /database/transaction: Esta pasta conterá os arquivos de log de transações. Como nem todos os SGBDs geram esses arquivos (ex: Firebird, InterBase), nem sempre ela será necessária O ideal é que seja formatada no sistema Ext2 devido a sua ótima velocidade.

Características dos sistemas de arquivos

A seguir veremos as principais características dos principais sistemas de arquivos do Linux:

  • XFS: Sistema de arquivos muito usado no IRIX (um tipo de Unix) e mantido pela SGI – Silicon Graphics - (veja mais em oss.sgi.com/projects/xfs/). É considerado um dos melhores, se não o melhor, sistema de arquivos para banco de dados. Já vem como padrão nos Linuxes com kernel versão 2.6, e em algumas distribuições que utilizam o kernel 2.4, como o SuSE.
  • ReiserFS: Sistema de arquivos desenvolvido por Hans Raiser e mantido pela Namesys (www.namesys.com). Atualmente na versão 4 (experimental). Segundo o site da Namesys, é o sistema de arquivo mais veloz já desenvolvido, no entanto não pude encontrar um comparativo oficial que comprove isso. A maioria das distribuições ainda traz a versão 3 do Raiser.
  • JFS: de propriedade da IBM, foi desenvolvido para rodar nos UNIXes que a IBM vendia. Após a “adoção” do Linux pela IBM, foi portado para trabalhar também nesse SO. É extremamente rápido e tem a vantagem de trabalhar com uma quantidade de dados muito superior aos demais sistemas de arquivos. O JFS perdeu um pouco de credibilidade no início devido a bugs e instabilidade, porém encontra-se estável atualmente.
  • Ext2: Sistema de arquivos padrão na maioria das distribuições com kernel 2.2. É o mais rápido por ser extremamente simples e sem grandes recursos. O maior problema do ext2 é a falta de confiabilidade, pois é muito sensível à instabilidade na máquina (travamentos, etc). É recomendado para partições que manipulam dados temporários, tais como /var/log/, /tmp, e o diretório de log de transações.
  • Ext3: Sistema de arquivos padrão na série atual do Kernel. É o sucessor do Ext2 e bem mais seguro, pois oferece o Journaling (também chamado de Loggin), mas peca no que diz respeito à velocidade.

Qual é a semelhança entre o Ext3, Raiserfs, JFS e XFS e porque excluir o Ext3 da lista de sistemas de arquivos para instalar o PostgreSQL?

Todos esses sistemas de arquivos trabalham com journaling (ou loggin). O journaling grava em uma área chamada journal qualquer tipo de operação que será realizada no disco. No caso de uma queda de energia, o sistema de arquivos verificará o que existe no journal, analisando todas as operações que estavam sendo realizadas antes da queda de energia. Assim, durante a montagem do sistema de arquivos, será possível desfazer ou finalizar operações que não foram concretizadas devido à queda.

O problema do ext3 é que ele guarda mais informações na área de journal do que o XFS, JFS e os outros, tornando-o mais lento tanto para o trabalho “cotidiano” quanto para a recuperação em casos de falha.

Qual sistema de arquivos usar?

Segundo o site fsbench.netnation.com, o XFS e o JFS têm seu desempenho muito próximo do EXT2, apesar de muitos utilizarem o XFS por considerá-lo um pouco mais rápido que o JFS. Para quem utiliza o RedHat 9 e não quer atualizar o Kernel para trabalhar com o XFS, sugiro utilizar o JFS, que é o padrão nessa versão da distribuição. Já para quem usa o Fedora Core, Slackware, e o Conectiva, terá disponível as vantagens do XFS sem necessidade de atualização do kernel. Não aconselho o uso do ReiserFS v4 em ambiente de produção por ainda estar em testes.

Considerando somente os sistemas de arquivo com versão estável, sugiro ficar com o XFS, pois é seguro, veloz, e permite uma administração flexível das partições formatadas com ele.

Determinando o tamanho das partições para o BD

Como a mudança do tamanho das partições, após sua definição inicial, nem sempre é uma tarefa fácil, devemos estimar previamente o tamanho da partição, visando um determinado período de tempo.

Supondo que nossa base de dados irá crescer em média 3Mb por dia, podemos calcular que no final de 1 mês teremos um acréscimo de 90MB, e que no final de um ano teremos um aumento de 1080MB na base, ou seja, pouco mais de 1GB.

Porém, não podemos ignorar no cálculo fatores como o crescimento do cliente, eventuais falhas, backups diários, etc. Na tentativa de amenizar um possível problema por falha no cálculo da estimativa, usaremos uma margem de segurança de 25%. Portanto, ao invés de 1080MB teríamos 1080 + 25% = 1350MB. Lembrando que este cálculo leva em consideração o período de 1 ano de crescimento. Passado esse período será necessário reavaliar as configurações.

Logicamente, esse é apenas um modelo de cálculo para estipular o tamanho da partição. Particularmente, costumo reservar o dobro do espaço determinado pelo cálculo, reservando assim espaço extra para tarefas como a criação de uma base adicional para manutenção, geração de backups, etc. Se você não tem noção prévia de qual seria o crescimento estimado do seu banco, sugiro deixar 10GB para a partição do BD, ou usar o LVM.

O LVM (Logical Volume Manager) possibilita o aumento do tamanho de uma partição, sem perda de dados. Ou seja, no caso da partição do BD, não haveria necessidade de dropar o banco, recriar a partição, recriar o banco, etc. O LVM cria volumes lógicos, onde, por exemplo, dois ou mais HDs podem ser visualizados como se fossem um único dispositivo. O espaço total de armazenamento desse volume lógico seria a soma dos tamanhos de cada HD. A desvantagem do LVM é que o desempenho da unidade lógica não é o mesmo se comparado com o acesso direto a um dispositivo físico, apesar de que dependendo do hardware envolvido, a perda de performance é imperceptível.

É possível utilizar o LVM para implementar um RAID 0. No entanto, não é sua função principal, e em uma situação como essa, a perda de um HD implicaria na perda total dos dados do volume. Recomendo utilizar o LVM em conjunto com RAID, preferencialmente via hardware. Falaremos mais sobre RAID em um próximo artigo.

A Listagem 1 apresenta os passos da criação de um LVM de forma direta e prática. As linhas em negrito identificam o que está sendo feito. Os parâmetros utilizados com o fdisk foram:

  • N – Nova partição;
  • T - Define qual o tipo de partição (LVM é o código 8e);
  • W – Salva a alteração e sai do fdisk;

Os outros comandos utilizados durante o processo foram:

  • vgscan: Varre todos os discos à procura de VGs (Volume Groups) e monta os arquivos /etc/lvmtab e /etc/lvmtab.d/* que são o banco de dados para todos os outros comandos do lvm;
  • pvcreate: Inicializa um volume físico para ser usado pelo LVM. O volume físico pode ser uma partição de disco, o disco inteiro, um meta-device ou um arquivo de loopback;
  • pvdisplay: Permite visualizar os atributos (tamanho, etc.) de um ou mais volumes físicos;
  • vgcreate: Cria o Volume Group (VG - “disco virtual”) utilizando o volume físico criado anteriormente pelo pvcreate;
  • lvcreate: Cria um novo Logical Volume (Volume Lógico) em um Volume Group já existente. Os parâmetros –L e –n determinam o tamanho e o nome do volume lógico, respectivamente.
  • mkfs: Constrói um sistema de arquivos no volume lógico recém criado;
  • mount: Anexa um sistema de arquivos de um dispositivo à um diretório;

Manipulação da partição que iremos criar o LVM, criaremos 6Gb para o LVM:


root@davi:/# fdisk /dev/hda

Command (m for help): n

First cylinder (754-2434, default 754): (ENTER)

Using default value 754

Last cylinder or +size or +sizeM or +sizeK (754-2434, default 2434): +6144M

Using default value 2434

Command (m for help): t

Partition number (1-8):

Hex code (type L to list codes): 8e

Changed system type of partition 8 to 8e (Linux LVM)

Command (m for help):w

Usando o VgScan pela primeira vez para criar o banco de dados para o LVM:

root@davi:/# vgscan

Usando o pvcreate para a criação de um volume físico para o /dev/hda8:

root@davi:/#  pvcreate /dev/hda8

Usando o pvdisplay para certificarmos que realmente o LVM atribui o /dev/hda8 como utilizável:

root@davi:/# pvdisplay /dev/hda8

pvdisplay -- "/dev/hda8" is a new physical volume of 6.0 GB

Usando o vgcreate para a criação do Disco Virtual chamado 'concat':

root@davi:/# vgcreate concat /dev/hda8

Usando o lvcreate para a criação de um volume lógico de 900M chamado 'backup' dentro do disco virtual 'concat':

root@davi:/# lvcreate -L 900M -n backup concat

Usando o mkfs.ext2 para a criação do sistema de arquivos para o volume 'backup':

root@davi:/# mkfs.ext2 /dev/concat/backup

Criando a pasta para acessar o volume 'backup'

root@davi:/# mkdir /mnt/backup

Usando o mount para a montagem deste sistema de arquivos:

root@davi:/# mount /dev/concat/backup /mnt/backup

Para termos certeza que montou:



root@davi:/# mount

root@dblinux:/# mount

/dev/hda1 on / type reiserfs (rw)

proc on /proc type proc (rw)

/dev/hda3 on /tmp type ext2 (rw)

/dev/hda5 on /var type ext2 (rw)

/dev/hda6 on /usr type reiserfs (rw)

/dev/hda7 on /usr/local type reiserfs (rw)

/dev/concat/backup on /mnt/backup  type ext2 (rw)
Listagem 1. Sequência de criação de um dispositivo LVM (sem definição de RAID 0)

QUADRO: Exemplo de criação de um lvm usando 3 partições distribuídas em vários HDs

Supondo que temos 3 partições (/dev/hda2, /dev/hdb1 e /dev/hdc1), livres para serem utilizadas, e que desejamos criar um volume group (VG) chamado "test_vg", os passos seriam:

1. Alterar o tipo das 3 partições para 0x8e (LVM) através do fdisk.

2. pvcreate /dev/hda2 /dev/hdb1 /dev/hdc1

3. vgcreate test_vg /dev/hda2 /dev/hdb1 /dev/hdc1

Com o volume group “test_vg” criado, poderíamos criar volumes lógicos de diferentes tamanhos, por exemplo, um volume lógico de 100MB usando o nome padrão lvol1 (/dev/test_vg/lvol1). Os passos seriam:

1. Criar o volume: lvcreate -L 100 test_vg

2. Criar um sistema de arquivos no volume test_vg: mkfs -t ext2 /dev/test_vg/lvol1

3. Montá-lo : mount /dev/test_vg/lvol1 /usr1

A Listagem 2 mostra um dispositivo criado pelo LVM. Neste servidor de BD, temos o HD /dev/hdb com 12GB e o /dev/hdc com 20Gb. O LVM fez uma concatenação dos HDs (hdb e hdc) criando o dispositivo virtual “/dev/concat/”; este dispositivo é conhecido como “volume group” (VG). No VG “/dev/concat”, podemos criar vários volumes lógicos (LVs – Logical Volumes). Na listagem 2, “/dev/concat/backup” é um LV. Vários LVs podem ser criados dentro de um VG (ex: /dev/concat/backup, /dev/concat/db), sendo que a soma de todos nunca ultrapassará o tamanho do VG. Note que os dispositivos hdb e hdc nem chegam a aparecer na listagem. Caso seja necessário adicionar mais espaço no volume “/dev/concat/backup”, bastaria adicionar mais um HD na máquina e utilizar os comandos vgextend e lvextend para que o LVM amplie o volume virtual (ver listagem 3).

Podemos criar um volume LVM mesmo tendo apenas um único HD instalado. Isso seria interessante caso esteja previsto a inclusão de mais HDs no futuro, assim estaríamos deixando o sistema já preparado para facilitar a expansão do volume.

O comando df (Disk Free) mostra o consumo do disco. O parâmetro –h foi utilizado para facilitar a compreensão dos resultados (-h significa “human format”). Sem ele, o resultado seria mostrado bytes.



[root@dblinux root]# df -h

Sistema de Arquivo         Tam     Usad    Disp    Uso%Montado   em

/dev/hda5                     1012M   308M    653M    33%            /

/dev/hda1                     99M     8.5M    86M       9%             /boot

none                            109M    0       109M       0%            /dev/shm

/dev/hda7                     1012M   687M    274M    72%           /tmp

/dev/hda2                     2.0G    1.1G    840M       57%           /usr

/dev/hda6                     1012M   54M     907M     6%            /var

/dev/concat/backup         32G    26G     6.0G       82%           /backup
2. Visualização dos volumes, incluindo o volume virtual criado pelo LVM.

Exemplo do vgextend e lvextend, supondo que o terceiro disco está em /dev/hdd e tem 10Gb:

[root@dblinux root]# pvcreate /dev/hdd 

  • Disponibilizando o HD para o LVM usar.

[root@dblinux root]# vgextend concat /dev/hdd

  • Colocando o HD de 10G no Volume Group 'concat'

[root@dblinux root]# lvextend /dev/concat/backup -L +10G 

  • Acrescenta 10Gb no Volume Lógico 'backup'

Agora precisamos estender o sistema de arquivos (“formatar” o pedaço a mais que foi acrescentado). No caso do sistema de arquivos utilizado for o XFS, usamos:

[root@dblinux root]# xfs_growfs /dev/concat/backup
3. Exemplo de utilização do vgextend e lvextend adicionando um novo HD em um volume criado pelo LVM.
É interessante usar no LVM um sistema de arquivos que permita a formatação apenas do espaço alocado posteriormente, sem necessidade de formatar todo o volume.

Note que para realizar os procedimentos das listagens 2 e 3 não seria necessário parar a máquina ou o servidor de BD, a não ser, é claro, para conectar fisicamente o novo HD, caso ele já não estivesse presente.

Criando os sistemas de arquivos

Antes de mais nada, devemos saber que podemos definir as partições e os sistemas de arquivos durante o processo de instalação do Linux. No entanto, geralmente quando isso é feito, apenas a configuração básica é utilizada, ou seja, necessitaremos posteriormente fazer os ajustes de performance. Um outro problema é que em algumas distribuições, nem todos os sistemas de arquivos estão disponíveis para serem utilizados no momento da instalação, o que nos obrigaria a formatá-los posteriormente com o sistema de arquivos desejado.

O mkfs (Make File System) é o utilitário responsável por criar o sistema de arquivos de uma determinada partição. Como sabemos, o Linux nos permite utilizar vários sistemas de arquivos diferentes - para indicar qual sistema deve ser usado na formatação, podemos simplesmente adicionar a sigla do sistema de arquivos no final do comando mkfs; por exemplo:


mkfs.jfs /dev/partição – Formatará usando o sistema de arquivo JFS

mkfs.xfs /dev/partição – Formatará usando o sistema de arquivo XFS

mk1fs.ext2 /dev/partição - Formatará usando o sistema de arquivo EXT2

Onde /dev/partição pode ser um disquete, uma partição de um HD, etc. No exemplo de um servidor 'hipotético', poderíamos formatar as partições /dev/hdc1 com o sistema de arquivos JFS e o /dev/hdc2 usando ext2:

Formatando o /dev/hdc1 para usarmos o XFS da SGI

mkfs.xfs /dev/hdc1

Formatando o /dev/hdc2 para usarmos o EXT2 do Linux.

mkfs.ext2 –b 4026 /dev/hdc2

Após a formatação das partições, é necessário montá-las (vincular as partições a um diretório). Para isto utilizaremos o arquivo /etc/fstab que é encontrado em todas as distribuições do Linux.

O arquivo /etc/fstab “ensina” o Linux a “vincular” (montar) partições, cd-roms, disquetes e compartilhamentos de rede a um determinado diretório durante o boot. Cada linha é responsável por um ponto de montagem. É através do /etc/fstab que o sistema é capaz de acessar o seu CD-ROM, por exemplo.

Inicialmente devemos editar o arquivo /etc/fstab e adicionar as linhas a seguir (note que # indica que a linha é um comentário).


# Dispositvo  Ponto de Montagem  Sis. Arq.        Opções de Montagem                            Dump  Ordem

/dev/hdc1      /database              xfs               defaults                                    1        2

/dev/hdc2      /database/transaction       ext2             rw,nodev,noatime,noexec,async              1        2

Onde:

  • Dispositivo: Partição que deseja montar.
  • Ponto de montagem : Diretório do Linux que dará acesso a partição montada.
  • Tipo: Tipo de sistema de arquivos usado na partição. No exemplo usamos ext2 e xfs.

Opções de montagem:

  • rw - Monta como leitura e gravação.
  • nodev – Não interpreta arquivos de blocos (exemplo, arquivos que estão no /dev).
  • noexec – Não permite a execução de binários.
  • async – Os dados não serão gravados imediatamente no HD, ficam em cachê.
  • Noatime – Não atualiza o tempo de acesso no arquivo.
  • Dump - Opção usada pelo comando dump (utilitário de Backup em fita DAT). O utilitário de backup selecionará apenas as unidades marcadas com '1'.
  • Ordem - Define a ordem que os sistemas de arquivos serão verificados na inicialização do sistema. Se zero, o sistema de arquivos não é verificado. O sistema de arquivo raiz deve estar configurado com “1” fazendo com que seja o primeiro a ser verificado.
  • defaults - Utiliza valores padrões de montagem (rw, suid, dev, exec, auto, nouser, e async).

Após configurar o fstab, devemos preparar os diretórios que serão vinculados às novas partições durante a montagem:


mkdir /database; (Criando a pasta database para usar o ponto de montagem)

cd /database

mkdir transaction (Criando a pasta transaction para usar o ponto de montagem)

mount /database (Pasta onde ficará o SGBD)

mount /database/transaction (Pasta para log de transações)

Com isso temos as partições preparadas e montadas. O próximo passo será fazer o tuning dos HDs!

Tuning de HDs padrão IDE

Para entendermos melhor o tuning de HDs, vamos conhecer um pouco da evolução dos HDs padrão IDE:

Antigamente, os HDs eram acessados diretamente pelo processador, causando um desperdício do mesmo. Para minimizar o problema, foi criado o controlador de DMA, sigla de “Direct Memory Access”, ou “Acesso Direto a Memória”. Essa tecnologia possibilitou o acesso direto à memória pelo HD ou pelos dispositivos que usam a interface IDE, sem a necessidade de “auxílio” do processador.

O computador utiliza um circuito chamado PIO (Programmed I/O) para se comunicar com o HD IDE. Existem 5 modos de operação PIO (PIO0 a PIO4), cada um utilizando um protocolo e uma taxa de transferência diferentes. Veja abaixo uma comparação das taxas de transferências utilizadas pelo controlador de PIO.

Nos dias de hoje, o padrão de mercado para HDs IDE é o Ultra-ATA, também conhecido como UDMA (Ultra-DMA). Com este padrão, é possível realizar transferências acima dos 33,3 MB/s, porém, é necessário que o HD e a placa mãe suportem o padrão UDMA.

Aproveitando o assunto, é importante explicar o conceito de nomenclatura de discos IDE no Linux. Na placa mãe, geralmente existem duas interfaces para conexões de HD, chamadas de IDE 0 e IDE 1. Vejamos como isso é identificado no Linux, dependendo da configuração do HD:

Quando o HD está configurado como MASTER (MESTRE):

  • Se estiver na IDE 0, então a identificação será /dev/hda
  • Se estiver na IDE 1, então a identificação será /dev/hdc

Quando o HD esta configurado como SLAVE (ESCRAVO):

  • Se estiver na IDE 0, então a identificação será /dev/hdb
  • Se estiver na IDE 1, então a identificação será /dev/hdd
HDPARM

Usaremos o utilitário HDPARM para “turbinar” o acesso a discos IDE no Linux. Esse utilitário habilita algumas opções de acesso ao disco e pode melhorar em até 50% a velocidade de leitura e gravação de dados. Logicamente, a utilização do hdparm deve ser feita com cuidado, pois parâmetros errados podem fazer a máquina bootar, travar ou perder dados.

O hdparm não faz “mágica”; ele apenas ativa no sistema operacional os “flags” de manipulação de HDs. O hdparm funciona para todos os HDs IDEs, lembrando que algumas opções só devem ser configuradas caso o HD específico suporte a funcionalidade configurada por ela. O único risco da utilização desta ferramenta é o de se habilitar um flag não suportado pelo HD em questão, e com isso corromper os dados. Portanto, tenha cuidado!

Inicialmente, executaremos um teste para saber o tempo e taxa de transferência de dados inicial (sem qualquer otimização) para servir de comparação durante a configuração dos parâmetros do hdparm. Para isso, execute o comando hdparm passando como parâmetro “-Tt” e o dispositivo /dev/hda (ver listagem 4).

Para saber se está havendo ganho de performance durante as próximas configurações, vamos comparar os valores das taxas de transferência do teste inicial com os valores obtidos a cada nova configuração. Se o valor da taxa de transferência aumentar, houve ganho de performance.



 [root@dblinux root]# hdparm -Tt /dev/hda

/dev/hda:

 Timing buffer-cache reads:   128 MB in  0.72 seconds =175.34 MB/sec

 Timing buffered disk reads:  64 MB in  2.22 seconds = 28.70 MB/sec
4. Retorno inicial do hdparm com a configuração padrão do HD.

O resultado indicado por “Timing buffer-cache reads” mede a transferência entre cachê, e é uma boa referência para detectar a eficiência do conjunto IDE/Memória/CPU. Já o resultado mostrado por “Timing buffered disk reads” ou “Transferências do disco para o buffer”, mede a taxa de transferência do disco propriamente dito.

Recomendo executar o teste no mínimo 3 vezes, e utilizar a média dos resultados obtidos, pois os resultados são sensíveis a qualquer I/O de disco ou processamento concorrente (o ideal é que não existam muitos processos sendo executados na máquina no momento em que o teste é realizado).

O próximo passo é habilitar o suporte a 32Bits de transferência de dados entre o barramento PCI e o controlador de disco, e em seguida verificar se houve ganho de desempenho. Praticamente todos os chipsets modernos suportam o modo 3 (transferência 32bits sincronizada). Veja a Listagem 5.



 [root@dblinux root]# hdparm -c 3 /dev/hda 

 /dev/hda:

 setting 32-bit IO_support flag to 3

 IO_support   =  3 (32-bit w/sync)

 
Agora veremos se houve melhorias na velocidade.

[root@dblinux root]# hdparm -Tt /dev/hda

/dev/hda:

 Timing buffer-cache reads:   128 MB in  0.73 seconds =178.20 MB/sec

 Timing buffered disk reads:  64 MB in  2.21 seconds = 28.88 MB/sec
5. Teste 2, com suporte a 32-bit I/O da IDE habilitado.

Observe o ganho de desempenho na listagem 5: Timing buffer-cache pulou de 175.34 MB/sec para 178.20 MB/sec e Timing buffered disk de 28.70 MB/sec para 28.88 MB/sec.

O próximo passo será habilitar a transferência de múltiplos setores (multcount) e verificar novamente se houve ganho de desempenho (ver listagem 6). O multcount diz qual é quantidade máxima de setores no disco que pode ser lido de uma vez. Configure para o valor máximo suportado pelo seu HD. Para saber o valor máximo suportado pelo HD, rode o hdparm com o parâmetro –i e verifique o valor de MaxMultSect.



[root@dblinux root]# hdparm -m 8 /dev/hda

/dev/hda:

 setting multcount to 8

 multcount    =  8 (on)

 

[root@dblinux root]# hdparm -Tt /dev/hda

/dev/hda:

 Timing buffer-cache reads:   128 MB in  0.71 seconds = 180.28 MB/sec

 Timing buffered disk reads:  64 MB in  2.21 seconds = 28.96 MB/sec

 
6. Teste 3, habilitar a transferência de múltiplos setores

Percebam que até aqui estamos ganhando desempenho com as configurações realizadas. Nosso próximo passo será habilitar a leitura seqüencial adiantada de setores do disco (ver listagem 7). Isso aumenta a velocidade na leitura de arquivos grandes, mas pode prejudicar o desempenho com arquivos pequenos. Na dúvida, deixe o valor igual ao do multicount para arquivos grandes. No exemplo utilizei o valor 32 pois se mostrou um valor adequado para a configuração. Também habilitaremos o uso do DMA (ver listagem 8).



 [root@dblinux root]# hdparm –a 32 /dev/hda

/dev/hda:

setting fs readahead to 32

readahead    = 32 (on)

[root@dblinux root]# hdparm -Tt /dev/hda

/dev/hda:

Timing buffer-cache reads:   128 MB in  0.70 seconds =182.86 MB/sec

Timing buffered disk reads:  64 MB in  2.21 seconds = 28.96 MB/sec

 
7. Teste 4, habilitar a leitura adiantada de 32 setores.


 [root@dblinux root]# hdparm –d 1 /dev/hda

/dev/hda:

 using_dma    =  1 (on)

 

[root@dblinux root]# hdparm -Tt /dev/hda

/dev/hda:

 Timing buffer-cache reads:   128 MB in  0.70 seconds =182.86 MB/sec

 Timing buffered disk reads:  64 MB in  2.21 seconds = 28.96 MB/sec
8. Teste 5, habilitar o uso do DMA.

Observe pelo resultado do teste 5 (listagem 8) que, neste caso, não houve ganho de velocidade. Isso indica que o acesso a DMA já estava ativo nativamente no driver. Dependendo da versão do kernel, a habilitação é feita automaticamente, no entanto, costumo sempre especificar o suporte a DMA durante o tuning oficial.

Agora colocaremos a configuração obtida no arquivo rc.local. Este possui uma funcionalidade parecida com o autoexec.bat do MS-DOS. Isso é necessário para que a configuração seja executada a cada boot do Linux. Veja a listagem 9.

Agora colocaremos no rc.local. Este arquivo é um tipo de AUTOEXEC.BAT do MS-DOS no Linux.


[root@dblinux root]# cat /etc/rc.d/rc.local

#!/bin/sh

#

# This script will be executed *after* all the other init scripts.

# You can put your own initialization stuff in here if you don't

# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

/sbin/hdparm  -c 3 -m 8 -a 32 -d 1 /dev/hda
9. Adicionar a configuração adquirida durante os testes para serem executadas no boot do Linux.

Os parâmetros “-c 3 –m 8 –a 32 –d 1” são eficientes para a maioria dos discos IDE. Observem que foram as mesmas opções detalhadas nos testes acima, porém, estamos passando os parâmetros para o hdparm de uma única vez. Lembrando que fizemos os testes e configuramos apenas o hda (HD Master na IDE 0) . Se mais de um HD estiver sendo utilizado, teremos uma linha de configuração para cada HD no arquivo /etc/rc.d/rc.local. A listagem 10 mostra o arquivo rc.local configurando 2 HDs (hda e hdb) de forma idêntica.

Em algumas distribuições do linux, o arquivo rc.local se encontra em um local diferente do diretório /etc/rc.d (geralmente em /etc/rc.local).

 

#!/bin/sh

#

# This script will be executed *after* all the other init scripts.

# You can put your own initialization stuff in here if you don't

# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

/sbin/hdparm  -c 3 -m 8 -a 32 -d 1 /dev/hda

/sbin/hdparm  -c 3 -m 8 -a 32 -d 1 /dev/hdb
10. Exemplo de rc.local configurando 2 HDs através do hdparm.

Podemos obter o mesmo efeito das 2 chamadas ao hdparm (ver listagem 9) em uma única linha de configuração, escrevendo-a da seguinte forma:

/sbin/hdparm  -c 3 -m 8 -a 32 -d 1 /dev/hd[a-b]

Para quem quiser aprender mais sobre o hdparm, existem inúmeros documentos disponíveis na internet, além do próprio man do Linux.

Os HDs do tipo SCSI possuem uma placa controladora específica, onde é possível realizar alguns ajustes de configuração diretamente na placa - por isso não temos utilitários genéricos de tuning para HDs SCSI.

Ajustando o I/O da máquina

Através do utilitário elvtune ajustaremos o kernel do sistema operacional fazendo-o trabalhar melhor com a leitura e a gravação de dados no dispositivo físico. Ele reorganiza os pedidos de Leitura/Escrita ao disco de acordo com seus setores, reduzindo assim os movimentos da cabeça do HD, e portanto o tempo de acesso.

Para os Linuxes com o kernel 2.6, o elvtune foi depreciado a favor do sysfs, apesar dele ainda funcionar com essa versão do kernel.

Basicamente os parâmetros utilizados são:

  • -r : Qual é a latência em blocos para leitura;
  • -w : Qual é a latência em blocos para gravação.

O algoritmo de ajuste de I/O do kernel utiliza uma fila de requisição de I/O em função do setor do disco. O elvtune ajusta os valores deste algoritmo de forma que possamos obter o melhor resultado possível dentro de uma determinada finalidade. Para quem estiver usando o kernel padrão do Red Hat 9.0 (versão 2.4.22), os valores mostrados abaixo são bastante interessantes na utilização com banco de dados:

/sbin/elvtune -r 64 -w 8192 /dev/hda

Os parâmetros configuram a latência de leitura para 64 blocos e de gravação para 8192. Estes valores são recomendados para trabalhar no kernel 2.4.22, mas já os utilizei com sucesso no kernel 2.6.5. Note que estamos configurando somente o dispositivo /dev/hda. Caso tenhamos outro dispositivo para configurar, devemos fazê-lo com uma nova chamada ao elvtune, indicando os parâmetros e o dispostivo.

Feito isto, é necessário editar o /etc/rc.d/rc.local e acrescentar a seguinte linha:


/sbin/elvtune -r 64 –w 8192        /dev/hda

O sysfs será discutido em um próximo artigo sobre tuning de servidores.

Glossário

BLOCK SIZE = É a menor informação do PostgreSQL, ou seja, 1 bloco de dados (menor informação armazenada). Seu tamanho é de 8Kb, isso significa que 100MB de banco usa 12.800 blocos.

KERNEL = O Kernel é o “núcleo” do sistema operacional; de uma forma muito simples, ele é o cérebro do sistema operacional.

PSEUDO ARQUIVO = Os arquivos contidos dentro da pasta /dev são uma ponte entre o usuário/SO e os dispositivos do computador; por exemplo: /dev/hda é a ponte com o HD que está na IDE 0, /dev/ttyS1 representa a porta serial e /dev/fd0 é o drive de disquete.

Conclusão

Apresentei nesse artigo uma noção básica de configuração do sistema operacional Linux visando obter maior desempenho com servidores de banco de dados. Vimos que não existe uma regra única para configuração, e por isso é necessário entender como o Linux trabalha. A configuração correta das partições, escolha do sistema de arquivos ideal e tuning do HD são essenciais para ganharmos eficiência no SGBD. Em um próximo artigo estaremos vendo algumas configurações de tuning específicas do Kernel do Linux, bem como alguns detalhes sobre RAID. Caso alguém tenha dúvidas, sinta-se à vontade para questionar.