PostgreSQL – mover tablespaces

É totalmente desaconselhado criar tablespaces na directoria DATA do pgsql. Podem ver-se vários avisos e explicações na net:
https://hunleyd.github.io/posts/Where-Not-To-Put-Your-Tablespaces/

Este post resulta de eu ter cometido este erro há muito tempo atrás (v8.4) e só agora estar a pagar por ele…

Como funcionam os tablespaces no postgres?

Tablespaces em pgsql são pastas onde são colocados os ficheiros de dados, e a teoria é que permitem espalhar os dados em diferentes discos para equilibrar os acessos e o desempenho. Também dão flexibilidade para gerir falta de espaço em disco, p.e. colocando um tablespace noutro disco que tem espaço, e que receberá determinados dados (todos os novos dados, só algumas tabelas, etc.).
Esta divisão também pode ser feita quando temos só um disco, ficando a bd preparada para um cenário futuro com mais discos.

O postgres tem 2 tablespaces iniciais: pg_default e pg_global.
O pg_global é destinado aos objectos de sistema, e o pg_default é obviamente onde são gravados os nossos dados.
A grande questão é: no disco, onde está o pg_default? Está na pasta DATA\base!

Localização em disco do tablespace pg_default

Existe uma directoria que baralha isto tudo: DATA\pg_tablespace. E que está vazia. É aqui que os utilizadores costumam baralhar o sistema (como eu), e pensando que esta pasta é onde está o tablespace default, vão raciocinar que podem criar os seus tablespaces ao “lado”, por exemplo DATA\meu_tablespace.

pg_tblspc – não mexer, não imitar. A pasta DATA é off-limits!

Lição – a directoria DATA não é para o user mexer! É de sistema, é gerida pelo postgres, está off-limits!
Pois mas eu não sabia… e vai daí, criei uma série de tablespaces aqui mesmo:

CREATE TABLESPACE meu_tablspc LOCATION 'C:\Program Files\PostgreSQL\9.3\data\meusdadosgeo';

Na versão actual, o postgres vai avisar que isto não se deve fazer. Eu já fiz isto há muito tempo (comecei na 8.4), e não me lembro de aviso nenhum.
Anos mais tarde, ao fazer upgrades com pg_upgrade comecei a ter os problemas respectivos…

Como funcionam os tablespaces e a directoria pg_tblspc?

Para criar um tablespace novo, temos de criar previamente a directoria onde queremos que o tablespace se localize.
Depois executamos o sql de criação do tablespace, e o postgres vai criar um link (ou junction no Windows) na pasta DATA\pg_tblspc.
Quer isto dizer que não são criadas sub-dirs – são criados apontadores para a pasta de cada tablespace.
Em Windows, podemos verificar que são junctions usando a linha de comando e fazendo um simples dir:

dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"
Directory of D:\Program Files\PostgreSQL\9.3\data\pg_tblspc
22/01/2019 13:23 .
22/01/2019 13:23 ..
22/01/2019 13:23 12493007 [D:\Program Files\PostgreSQL\tables
paces_digc\sisma_tblspc]
22/01/2019 13:23 18357 [D:\Program Files\PostgreSQL\tablespac
es_digc\always_tblspc]

Podemos ver que a sub-dir 18357 é na realidade um junction que aponta para uma dir noutro local.

Ao criarmos os tablespaces dentro da pasta DATA estão a ver a confusão, certo? Estamos efectivamente a alterar a forma como o postgres gere os tablespaces, criando links/junctions que apontam para a pasta DATA. Quando quiserem usar o pg_upgrade, que vai tentar perceber a estrutura dos tablespaces, e não vai conseguir… resultando em erro de upgrade.

Se está nesta situação terá de a corrigir. Não é difícil mas como temos de alterar a estrutura e localização dos ficheiros de dados da bd é arriscado, e basta um erro para arruinar a bd. Portanto, antes de mais nada faça um snapshot da vm do postgres, ou se não é vm, faça um backup integral da bd. (better paranoid than dead)

Como corrigir?

Os tablespaces, dizem os docs, devem ser criados numa pasta cujo dono é a conta do sistema operativo que controla o serviço do postgres. No meu caso é “Network Service”.
Assim, optei por criar uma pasta para todos os meus tablespaces na dir de instalação do postgres. Isto porque em Windows, o postgres instala as versões como sub-dirs desta:

C:\Program Files\PostgreSQL\9.3
C:\Program Files\PostgreSQL\9.5

Assim, a minha pasta será criada desta forma:
C:\Program Files\PostgreSQL\meus_tablespaces

Fica à prova de apagar acidentalmente… ou pelo menos parece fazer parte da instalação o que fará pensar 2x…

C:\Program Files\PostgreSQL\9.3
C:\Program Files\PostgreSQL\9.5
C:\Program Files\PostgreSQL\tablespaces_adicionais

Depois, paramos a bd, e vamos apagar os junctions e recriá-los apontando para subpastas correctas.

Receita

A seguir apresento, em jeito de resumo, uma sequência de passos para corrigir a situação. Os exemplos consideram que existem 2 tablespaces para corrigir. (Será, naturalmente, melhor exportar os comandos para ficheiros de texto e criar pequenos scripts para ajudar…)

1) parar o serviço do postgres

2) vamos anotar as pastas dos nossos tablespaces, e os números dos junctions/links, vendo o conteúdo da pasta DATA\pg_tblspc:

 dir "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc"
12493007 [D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc]
18357 [D:\Program Files\PostgreSQL\9.3\data\always_tblspc]

3) vamos mover as dirs dos nossos tablespaces para a nova localização saudável

move "D:\Program Files\PostgreSQL\9.3\data\sisma_tblspc"   "D:\Program Files\PostgreSQL\tablespaces_adicionais"
move "D:\Program Files\PostgreSQL\9.3\data\always_tblspc" "D:\Program Files\PostgreSQL\tablespaces_adicionais"

4) vamos apagar os junctions todos na pasta DATA\pg_tablspc

rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007
rd D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357

5) vamos recriar os junctions apontando-os para as dir correctas

mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\12493007" "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"
mklink /J "D:\Program Files\PostgreSQL\9.3\data\pg_tblspc\18357" "D:\Program Files\PostgreSQL\tablespaces_adicionaisc\always_tblspc"

6) iniciamos o serviço do postgres

E testamos, com diversas queries, e verificamos se no log surgem erros. Mas em principio se a bd iniciou não haverá problemas.
Se ocorrer um erro ao iniciar o serviço e não conseguir perceber a razão, terá de repor a situação, usando o snapshot da vm, ou restaurando toda a bd a partir do backup que fez.

A partir daqui, podemos ver que a estrutura dos tablespaces em disco ficou:

dir "D:\Program Files\PostgreSQL\tablespaces_adicionais"
Volume in drive D is Data
Volume Serial Number is 9CB2-EBBD
Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais
22/01/2019 13:18 .
22/01/2019 13:18 ..
25/01/2019 18:58 always_tblspc
25/01/2019 18:58 sisma_tblspc

Interessante também, e relevante para um processo de upgrade, é ver o conteúdo destas pastas:

dir "D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc"
Volume in drive D is Data
Volume Serial Number is 9CB2-EBBD
Directory of D:\Program Files\PostgreSQL\tablespaces_adicionais\sisma_tblspc
25/01/2019 18:58 .
25/01/2019 18:58 ..
24/01/2019 18:59 PG_9.3_201306121

Ou seja, o postgresql cria uma sub-pasta marcando a versão do postgres que coloca aqui os dados. Num upgrade serão criadas aqui sub-pastas correspondentes à nova versão.

E isso fica para um próximo post… Até breve.

Leave a Reply

Your email address will not be published. Required fields are marked *