[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]

161. PostgreSQL: struttura e preparazione

PostgreSQL è un DBMS (Data Base Management System) relazionale esteso agli oggetti. In questo capitolo si vuole introdurre al suo utilizzo e accennare alla sua struttura, senza affrontare le particolarità del linguaggio di interrogazione. Il nome lascia intendere che si tratti di un DBMS in grado di comprendere le istruzioni SQL, anche se per il momento l'aderenza a quello standard è solo parziale.

161.1 Struttura dei dati nel filesystem

PostgreSQL, a parte i programmi binari, gli script e la documentazione, colloca i file di gestione delle basi di dati a partire da una certa directory, che nella documentazione originale viene definita PGDATA. Questo è il nome di una variabile di ambiente che può essere utilizzato per informare i vari programmi di PostgreSQL della sua collocazione; tuttavia, di solito questo meccanismo della variabile di ambiente non viene utilizzato, specificando tale directory in fase di compilazione dei sorgenti.

Questa directory corrisponde solitamente anche alla directory home dell'utente di sistema per l'amministrazione di PostgreSQL, che dovrebbe essere postgres, per cui si potrebbe anche indicare come ~postgres/.

In ogni caso, questa directory è normalmente /var/lib/pgsql/, e tutto ciò che si trova al suo interno appartiene all'utente postgres, anche se i permessi per il gruppo e gli altri utenti variano a seconda della circostanza.

Inizialmente, questa directory dovrebbe contenere una serie di file il cui nome inizia per pg_*. Alcuni di questi sono file di testo, altri sono dei cataloghi, ovvero delle tabelle che servono alla gestione del DBMS e non fanno parte delle basi di dati normali. Se per qualche ragione si utilizza l'utente postgres, essendo questa la sua directory personale, potrebbero apparire altri file che riguardano la personalizzazione di questo utente (.profile, .bash_history, o altre cose simili, in funzione dei programmi che si utilizzano).

All'interno di questa directory si trova normalmente la sottodirectory base/, da cui si articolano le basi di dati che vengono create di volta in volta: ogni base di dati ottiene una sua sottodirectory ulteriore. Per creare una nuova base di dati, PostgreSQL fa uso di una base di dati di partenza: template1. I file di questa si trovano all'interno di base/template1/.

161.1.1 Opzioni per la definizione della directory «PGDATA» attraverso la riga di comando

Tutti i programmi che compongono il sistema di PostgreSQL, che hanno la necessità di sapere dove si trovano i dati, oltre al meccanismo della variabile di ambiente PGDATA permettono di indicare tale directory attraverso un'opzione della riga di comando. I programmi più importanti, e precisamente postmaster e createdb riconoscono l'opzione -D. Come si può intuire, l'utilizzo di questa opzione, o di un'altra equivalente per gli altri programmi, fa in modo che l'indicazione della variabile PGDATA non abbia effetto.

161.1.2 Amministratore

Una particolarità di PostgreSQL sta nella definizione dell'amministratore di questo servizio. In pratica potrebbe trattarsi di una persona diversa dall'amministratore del sistema, l'utente root, e come accennato si tratta generalmente dell'utente postgres.

Quando la propria distribuzione GNU/Linux è già predisposta per PostgreSQL, l'utente postgres dovrebbe già essere stato previsto (non importa il numero UID che gli sia stato abbinato), ma quasi sicuramente la password dovrebbe essere «impossibile», come nell'esempio seguente:

postgres:!:100:101:PostgreSQL Server:/var/lib/pgsql:/bin/bash

Come si vede, il campo della password è occupato da un punto esclamativo che di fatto impedisce l'accesso all'utente postgres.

A questo punto si pongono due alternative, a seconda che si voglia affidare la gestione del DBMS allo stesso utente root oppure che si voglia incaricare per questo un altro utente. Nel primo caso non occorrono cambiamenti: l'utente root può diventare postgres quando vuole con il comando su;

su postgres

nel secondo caso, l'attribuzione di una password all'utente postgres permetterà a una persona diversa di amministrare il DBMS.

passwd postgres

È bene ripetere che la directory home di questo utente fittizio (in questo caso /var/lib/pgsql/) coincide con il punto di inizio della struttura dei dati del DBMS.

161.1.3 Creazione del sistema di basi di dati

La prima volta che si installa PostgreSQL, è molto probabile che venga predisposta automaticamente la directory ~postgres/. Se così non fosse, o se per qualche motivo si dovesse intervenire manualmente, si può utilizzare initdb, che per farlo si avvale di alcune informazioni contenute nella directory definita dalla variabile di ambiente PGLIB, che dovrebbe corrispondere a /usr/lib/pgsql/.

initdb [<opzioni>]

Lo schema sintattico mostra in modo molto semplice l'uso di initdb. Se si definiscono correttamente le variabili di ambiente PGLIB e PGDATA, si può fare anche a meno delle opzioni, diversamente diventa necessario dare queste due informazioni attraverso le opzioni della riga di comando.

La directory definita dalla variabile PGLIB, ovvero quella che di solito corrisponde a /usr/lib/pgsql/, serve a initdb per raggiungere due file: global1.bki.source e local1_template1.bki.source. Questi due sono in pratica degli script che servono rispettivamente a generare i file della directory iniziale del sistema di basi di dati, ovvero ~postgres/* (/var/lib/pgsql/*), e della base di dati template1, corrispondente di solito al contenuto della directory ~postgres/base/template1/. In breve, template1 è lo scheletro utilizzato per la creazione di ogni nuova base di dati.

Prima di avviare initdb, è bene utilizzare l'identità dell'utente amministratore di PostgreSQL:

su postgres

Successivamente, avviando initdb, con le indicazioni corrette delle directory corrispondenti alle variabili PGLIB e PGDATA, si ottengono delle segnalazioni simili a quelle seguenti (si presume che la directory iniziale PGDATA sia già stata creata e appartenga all'utente postgres).

postgres$ initdb --pglib=/usr/lib/pgsql --pgdata=/var/lib/pgsql

We are initializing the database system with username postgres (uid=100).
This user will own all the files and must also own the server process.

Creating Postgres database system directory /var/lib/pgsql/base

Creating template database in /var/lib/pgsql/base/template1

Creating global classes in /var/lib/pgsql/base

Adding template1 database to pg_database...

Vacuuming template1
Creating public pg_user view
Creating view pg_rules
Creating view pg_views
Creating view pg_tables
Creating view pg_indexes
Loading pg_description

Alcune opzioni

--pglib=<directory-pglib> | -l <directory-pglib>

Permette di definire la directory all'interno della quale initdb deve cercare gli script che servono a ricreare il sistema di basi di dati di PostgreSQL.

--pgdata=<directory-pgdata> | -r <directory-pgdata>

Stabilisce la directory iniziale del sistema di basi di dati di PostgreSQL che si vuole creare.

--username=<amministratore> | -u <amministratore>

Questa opzione, permette eventualmente di utilizzare initdb con i privilegi dell'utente root, definendo in questo modo chi debba essere l'amministratore di PostgreSQL. In generale, questa opzione potrebbe anche non funzionare, e per evitare problemi, conviene avviare initdb utilizzando l'identità dell'amministratore PostgreSQL.

--template | -t 

Fa in modo di ricostruire lo scheletro template1, senza intervenire negli altri dati del sistema di basi di dati. Può essere utile se per qualche motivo template1 risulta danneggiato.

161.2 Impostazione client/server e amministrazione

Il DBMS di PostgreSQL si basa su un sistema client/server, in cui, il programma che vuole interagire con una base di dati determinata deve farlo attraverso delle richieste inviate a un server. In questo modo, il servizio può essere esteso anche attraverso la rete.

L'organizzazione di PostgreSQL prevede la presenza di un demone sempre in ascolto (può trattarsi di un socket di dominio UNIX o anche di una porta TCP, e in tal caso si tratta normalmente del numero 5432). Quando questo riceve una richiesta valida per iniziare una connessione, attiva una copia del server vero e proprio (back-end), a cui affida la connessione con il client. Il demone in ascolto per le richieste di nuove connessioni è postmaster, mentre il server è postgres. *1*

Generalmente, il demone postmaster viene avviato attraverso la procedura di inizializzazione del sistema, in modo indipendente da inetd. In pratica, di solito si utilizza uno script collocato all'interno di /etc/rc.d/init.d/, o in un'altra collocazione simile, per l'avvio e l'interruzione del servizio.

Durante il funzionamento del sistema, quando alcuni client sono connessi, si può osservare una dipendenza del tipo rappresentato dallo schema seguente:

...
|
|-postmaster-+-postgres
|            +-postgres
|            `-postgres
...

161.2.1 # postmaster

postmaster [<opzioni>]

postmaster è il demone che si occupa di restare in ascolto in attesa di una richiesta di connessione con un server postgres (il back-end in questo contesto). Quando riceve questo tipo di richiesta mette in connessione il client (o front-end) con una nuova copia del server postgres.

Per poter compiere il suo lavoro deve essere a conoscenza di alcune notizie essenziali, tra cui in particolare: la collocazione di postgres (se questo non è in uno dei percorsi della variabile PATH), e la directory da cui si dirama il sistema di file che costituisce il sistema delle varie basi di dati. Queste notizie possono essere predefinite, nella configurazione usata al momento della compilazione dei sorgenti, oppure possono essere indicate attraverso la riga di comando.

postmaster, e soprattutto i processi da lui controllati (il back-end), gestiscono una serie di file che compongono le varie basi di dati del sistema. Trattandosi di un sistema di gestione dei dati molto complesso, è bene evitare di inviare il segnale SIGKILL (9), perché con questo si provoca la conclusione immediata del processo destinatario e di tutti i suoi discendenti, senza permettere una conclusione corretta. Al contrario, gli altri segnali sono accettabili, come per esempio un SIGTERM che viene utilizzato in modo predefinito quando si esegue un kill.

Alcune opzioni

-D <directory-dei-dati>

Permette di specificare la directory di inizio della struttura dei dati del DBMS.

-S

Specifica che il programma deve funzionare in modo «silenzioso», senza emettere alcuna segnalazione, e soprattutto, diventando un processo discendente direttamente da quello iniziale (Init), disassociandosi dalla shell e quindi dal terminale da cui è stato avviato.

Questa opzione viene utilizzata particolarmente per avviare il programma all'interno della procedura di inizializzazione del sistema, quando non sono necessari dei controlli di funzionamento.

-b <percorso-del-backend>

Se il back-end, ovvero il programma postgres, non si trova in uno dei percorsi contenuti nella variabile di ambiente PATH, è necessario specificare la sua collocazione (il percorso completo) attraverso questa opzione.

-d [<livello-di-diagnosi>]

Questa opzione permette di attivare la segnalazione di messaggi diagnostici (debug), da parte di postmaster e del back-end, a più livelli di dettaglio:

Di norma, i messaggi diagnostici vengono emessi attraverso lo standard output da parte di postmaster, anche quando si tratta di messaggi provenienti dal back-end. Perché abbia significato usare questa opzione, occorre avviare postmaster senza l'opzione -S.

-i

Abilita le connessioni TCP/IP. Senza l'indicazione di questa opzione, sono ammissibili solo le connessioni locali attraverso socket di dominio UNIX (UNIX domain socket).

-p <porta>

Se viene avviato in modo da accettare le connessioni attraverso la rete (l'opzione -i), specifica una porta di ascolto diversa da quella predefinita (5432).

Esempi

su postgres -c 'postmaster -S -D/var/lib/pgsql'

L'utente root, avvia postmaster dopo essersi trasformato temporaneamente nell'utente postgres (attraverso su), facendo in modo che il programma si disassoci dalla shell e dal terminale, diventando un discendente da Init. Attraverso l'opzione -D si specifica la directory di inizio dei file della base di dati.

su postgres -c 'postmaster -i -S -D/var/lib/pgsql'

Come nell'esempio precedente, specificando che si vuole consentire, in modo preliminare, l'accesso attraverso la rete. *2*

su postgres -c 'nohup postmaster -D/var/lib/pgsql > /var/log/pglog 2>&1 &'

L'utente root, avvia postmaster in modo simile al precedente, dove in particolare viene diretto lo standard output all'interno di un file, per motivi diagnostici. Si osservi l'utilizzo di nohup per evitare l'interruzione del funzionamento di postmaster all'uscita del programma su.

su postgres -c 'nohup postmaster -D/var/lib/pgsql -d 1 > /var/log/pglog 2>&1 &'

Come nell'esempio precedente, con l'attivazione del primo livello diagnostico nei messaggi emessi.

161.2.2 Localizzazione

A partire dalla versione 6.4 di PostgreSQL, inizia l'introduzione di un sistema di gestione delle localizzazioni. La sua attivazione dipende dalle opzioni che vengono definite in fase di compilazione, per cui potrebbe anche succedere che la propria distribuzione GNU/Linux disponga di una versione di PostgreSQL che non è in grado di gestire la localizzazione.

La localizzazione va applicata al server, ovvero al sistema di gestione dei dati, e non al client. Questa è una situazione un po' strana rispetto al solito, dove ogni utente configura per sé il proprio ambiente. Infatti, la scelta della localizzazione dei dati, deve essere fatta al livello della base di dati, e non può essere cambiata a piacimento, a seconda dei punti di vista.

Di conseguenza, la configurazione delle variabili LC_*, o eventualmente di LANG, deve avvenire per l'ambiente riferito al funzionamento di postmaster, e per questo occorre preparare uno script apposito.

#!/bin/sh

LANG=it_IT.ISO-8859-1
# LC_CTYPE=it_IT.ISO-8859-1
# LC_COLLATE=it_IT.ISO-8859-1
# LC_MONETARY=it_IT.ISO-8859-1
export LANG
# export LC_CTYPE LC_COLLATE LC_MONETARY

/usr/bin/postmaster -i -S -D/var/lib/pgsql

Lo script che si vede sopra, serve a definire la variabile di ambiente LANG, a esportarla, e ad avviare postmaster. Questo script deve essere avviato dalla procedura di inizializzazione del sistema, all'interno della quale sarà utilizzato presumibilmente su, in modo da attribuire l'identità dell'utente amministratore di PostgreSQL. Se si usa un sistema di script per l'avvio o la conclusione dei servizi, cosa che di solito si colloca nella directory /etc/init.d/, o /etc/rc.d/init.d/, potrebbe essere necessario intervenire su quello che si occupa di avviare postmaster.

#!/bin/sh
case "$1" in
  start)
	echo -n "Avvio del servizio PostgreSQL: "
	su -l postgres -c '/usr/bin/postmaster -i -S -D/var/lib/pgsql'
	echo
	;;
  stop)
	echo -n "Disattivazione del servizio PostgreSQL: "
	killall postmaster
	echo
	;;
  *)
	echo "Utilizzo: postgresql {start|stop}"
	exit 1
esac

Quello che si vede sopra, è lo scheletro della struttura case tipica di un tale script. Volendo modificare la localizzazione predefinita in fase di compilazione, occorre lo script mostrato prima. Si suppone che lo script con il quale si modificano le variabili di localizzazione e si avvia postmaster, sia /usr/bin/avvia_postmaster; la modifica da apportare all'esempio appena visto è quella seguente:

...
case "$1" in
  start)
	echo -n "Avvio del servizio PostgreSQL: "
	# su -l postgres -c '/usr/bin/postmaster -i -S -D/var/lib/pgsql'
	su -l postgres -c '/usr/bin/avvia_postmaster'
	echo
	;;
...

Oltre alla localizzazione attraverso le variabili di ambiente tradizionali, si può intervenire sulla variabile PGDATESTYLE, il cui scopo è quello di definire la forma di visualizzazione delle date. La tabella 161.1 elenca le parole chiave che si possono assegnare a questa variabile e l'effetto che ne deriva.

Stile Descrizione Esempio
ISO ISO 8601 1999-12-31
SQL Tipo tradizionale 12/31/1999
German 31.12.1999

Tabella 161.1: Elenco dei formati di data gestibili con PostgreSQL.

Probabilmente, la cosa migliore è utilizzare il formato ISO, e questo potrebbe anche diventare quello predefinito nelle prossime versioni di PostgreSQL. Volendo estendere lo script per l'avvio di postmaster, presentato all'inizio, basta aggiungere l'impostazione della variabile PGDATESTYLE:

#!/bin/sh

LANG=it_IT.ISO-8859-1
# LC_CTYPE=it_IT.ISO-8859-1
# LC_COLLATE=it_IT.ISO-8859-1
# LC_MONETARY=it_IT.ISO-8859-1
export LANG
# export LC_CTYPE LC_COLLATE LC_MONETARY
PGDATESTYLE=ISO
export PGDATESTYLE

/usr/bin/postmaster -i -S -D/var/lib/pgsql

161.2.3 Organizzazione degli utenti e delle basi di dati

Per fare in modo che gli utenti possano accedere al DBMS, occorre che siano stati registrati all'interno del sistema di PostgreSQL stesso. In pratica, può trattarsi solo di utenti già riconosciuti nel sistema operativo, che vengono aggiunti e accettati anche da PostgreSQL. Per l'inserimento di questi utenti si utilizza createuser, come nell'esempio seguente:

su postgres[Invio]

postgres$ createuser[Invio]

Enter name of user to add---> daniele[Invio]

Enter user's postgres ID or RETURN to use unix user ID: 500 -> [Invio]

In tal modo è stato definito l'inserimento dell'utente daniele, confermando il suo numero UID.

Is user "daniele" allowed to create databases (y/n) y[Invio]

All'utente daniele è stato concesso di creare delle nuove basi di dati.

Is user "daniele" allowed to add users? (y/n) n[Invio]

All'utente non viene concesso di aggiungere altri utenti.

createuser: daniele was successfully added

Da questo esempio si può comprendere quali siano le possibilità di attribuzione di privilegi ai vari utenti del sistema DBMS. In particolare, è opportuno osservare che ogni base di dati appartiene all'utente che lo ha creato, il quale diventa il suo amministratore particolare (per la precisione il DBA).

L'eliminazione di un utente PostgreSQL avviene in modo simile attraverso destroyuser, come nell'esempio seguente:

su postgres[Invio]

postgres$ destroyuser[Invio]

Enter name of user to delete ---> daniele[Invio]

destroyuser: delete of user daniele was successful.

L'eliminazione di un utente PostgreSQL comporta anche l'eliminazione delle basi di dati a lui appartenenti.

Le informazioni sugli utenti autorizzati a gestire in qualunque modo il sistema di basi di dati sono archiviate nel file ~postgres/pg_shadow, visibile anche attraverso la vista definita dal file ~postgres/pg_user. È utile sapere questo per comprendere il significato dei messaggi di errore, quando fanno riferimento a questo file.

161.2.4 Controllo diagnostico

Inizialmente, l'utilizzo di PostgreSQL si può dimostrare poco intuitivo, soprattutto per ciò che riguarda le segnalazioni di errore, spesso troppo poco esplicite. Per permettere di avere una visione un po' più chiara di ciò che accade, sarebbe bene fare in modo che postmaster produca dei messaggi diagnostici, possibilmente diretti a un file o a una console virtuale inutilizzata.

Nella sezione in cui si descrive il funzionamento di postmaster appaiono alcuni esempi di avvio di questo programma, in modo da generare e conservare queste informazioni diagnostiche. L'esempio seguente, in particolare, avvia postmaster in modo manuale e, oltre a conservare le informazioni diagnostiche in un file, le visualizza continuamente attraverso una console virtuale inutilizzata (l'ottava).

su postgres[Invio]

nohup postmaster -D/var/lib/pgsql -d 1 > /var/log/pglog 2>&1 &[Invio]

exit[Invio]

nohup tail -f /var/lib/pgsql > /dev/tty8 &[Invio]

161.3 Accesso e autenticazione

L'accesso alle basi di dati viene consentito attraverso un sistema di autenticazione. I sistemi di autenticazione consentiti possono essere diversi, e dipendono dalla configurazione di PostgreSQL fatta all'atto della compilazione dei sorgenti.

Il file di configurazione pg_hba.conf (Host-Based Authentication), che si trova della directory home dell'utente postgres, cioè l'inizio della struttura delle basi di dati, serve per controllare il sistema di autenticazione una volta installato PostgreSQL.

L'autenticazione degli utenti può avvenire in modo incondizionato (trust), e ciò si fa di solito quando chi accede è un utente del sistema presso cui è in funzione PostgreSQL stesso; in pratica ci si fida del sistema di controllo fatto dal sistema operativo.

L'autenticazione può essere semplicemente disabilitata, nel senso di impedire qualunque accesso incondizionatamente. Questo può servire per impedire l'accesso da parte di un certo gruppo di nodi.

L'accesso può essere controllato attraverso l'abbinamento di una password agli utenti di PostgreSQL. Queste password possono essere conservate in un file di testo con una struttura simile a quella di /etc/passwd, oppure nel file ~postgres/pg_shadow, che in pratica è una tabella (questo particolare verrà ripreso in seguito).

Inoltre, l'autenticazione può avvenire attraverso un sistema Kerberos, oppure attraverso il protocollo IDENT (descritto nel capitolo 186). In quest'ultimo caso, ci si fida di quanto riportato dal sistema remoto il quale conferma o meno che la connessione appartenga a quell'utente che si sta connettendo.

161.3.1 ~postgres/pg_hba.conf

Il file ~postgres/pg_hba.conf permette di definire quali nodi possono accedere al servizio DBMS di PostgreSQL, eventualmente stabilendo anche un abbinamento specifico tra basi di dati e nodi di rete.

Le righe vuote e il testo preceduto dal simbolo # vengono ignorati. I record (cioè le righe contenenti le direttive del file in questione), sono suddivisi in campi separati da spazi o caratteri di tabulazione. Il formato può essere riassunto nei due modelli sintattici seguenti:

local <database> <autenticazione-utente> [<mappa>]

host <database> <indirizzo-IP> <maschera-degli-indirizzi> <autenticazione-utente> [<mappa>]

Nel primo caso si intendono controllare gli accessi provenienti da client avviati nello stesso sistema locale, utilizzando un socket di dominio UNIX; nel secondo si fa riferimento ad accessi attraverso la rete (connessioni TCP).

Perché il sistema possa funzionare correttamente, sono sempre presenti almeno i record seguenti:

# tipo	database	IP		maschera		autorizz.
#
local        all                                        	trust
host         all         127.0.0.1     255.255.255.255  	trust     

Ciò consente l'accesso senza altre misure di sicurezza a tutti i client che accedono dallo stesso sistema locale attraverso un socket di dominio UNIX, e agli utenti dello stesso nodo locale (localhost), a tutte le basi di dati.

L'esempio seguente permette l'accesso da parte di utenti provenienti dalla rete locale 192.168.___.___, alla base di dati nostro_db, affidando il compito di riconoscimento al sistema remoto da cui avviene la connessione e utilizzando il nome dell'utente, fornito in questo modo, come nome di utente PostgreSQL.

# tipo	database	IP		maschera	autorizz.
#
host	nostro_db	192.168.0.0	255.255.0.0	ident	sameuser

L'esempio seguente, è simile al precedente, con la differenza che gli accessi dalla rete indicata richiedono una password, che PostgreSQL conserva nel file di testo ~postgres/passwd (il nome indicato nell'ultimo campo).

# tipo	database	IP		maschera	autorizz.
#
host	nostro_db	192.168.0.0	255.255.0.0	password  passwd

Questo file di configurazione viene fornito già con alcuni esempi commentati.

161.3.2 Gestione delle password in chiaro

Con il sistema di autenticazione definito dalla parola chiave password è possibile utilizzare un file di testo simile a /etc/passwd o a /etc/shadow per annotare gli utenti PostgreSQL e le password cifrate relative. Per esempio, se nel file ~postgres/pg_hba.conf compare il record

host	nostro_db	192.168.0.0	255.255.0.0	password  utenti

gli utenti che accedono attraverso un client avviato dai nodi della sottorete 192.168.*.* devono identificarsi attraverso l'indicazione di una password che PostgreSQL può trovare nel file di testo ~postgres/utenti. Questo file potrebbe essere simile a quello seguente:

tizio:wsLHjp.FutW0s
caio:a6%i/.45w2q4

Se questo file dovesse contenere dei campi aggiuntivi (separati con i soliti due punti), questi verrebbero semplicemente ignorati.

Quando il client deve accedere utilizzando questo tipo di autenticazione, deve presentarsi con il nominativo-utente e la password. Quando si usa il programma psql che verrà descritto in seguito, occorre specificare l'opzione -u.

La password cifrata che si colloca nel secondo campo del record di questo file è ottenuta con la solita funzione di sistema crypt(). Per inserire facilmente un utente, o per cambiare la password di un utente registrato precedentemente, si utilizza il programma pg_passwd, indicando semplicemente in quale file intervenire.

pg_passwd <file>

L'utilizzo è banale, come si vede dall'esempio seguente in cui si aggiunge l'utente semproni (è importante ricordare di operare in qualità di utente postgres).

cd ~postgres[Invio]

su postgres[Invio]

postgres:~$ pg_passwd utenti[Invio]

Username: semproni[Invio]

New password: ******[Invio]

Re-enter new password: ******[Invio]

161.4 Gestione delle basi di dati

Per poter gestire una base di dati occorre prima crearla. Ciò si ottiene normalmente attraverso lo script createdb, avviato con i privilegi adatti, cioè quelli di un utente a cui ciò è consentito. Nello stesso modo, attraverso lo script destroydb, si può eliminare un'intera base di dati.

PostgreSQL non distingue tra lettere maiuscole e minuscole quando si tratta di nominare le basi di dati, le relazioni (le tabelle o gli oggetti a seconda della definizione che si preferisce utilizzare), e gli elementi delle relazioni. Tuttavia, in certi casi si verificano degli errori inspiegabili dovuti alla scelta dei nomi che in generale conviene indicare sempre solo con lettere minuscole.

161.4.1 Creazione di una base di dati

La creazione di una base di dati è in pratica la creazione di una serie di file all'interno di una directory con lo stesso nome usato per identificare la base di dati stessa. Questa operazione ha luogo utilizzando una struttura di partenza già predisposta: di solito si tratta di template1.

Le directory delle basi di dati si articolano a partire da ~postgres/base/. Quando si crea l'ipotetica base di dati mio_db, ciò che si ottiene in pratica è la copia della directory ~postgres/base/template1/ in ~postgres/base/mio_db/. *4*

Come già accennato, una base di dati può essere creata solo da un utente autorizzato precedentemente per questo scopo. Di solito si utilizza lo script createdb, come nell'esempio seguente in cui si crea la base di dati mio_db.

createdb mio_db

L'utente che ha creato una base di dati è automaticamente il suo amministratore, ovvero colui che può decidere eventualmente di eliminarla.

PostgreSQL pone dei limiti nella scelta dei nomi delle basi di dati. Non possono superare i 16 caratteri e il primo di questi deve essere alfabetico, oppure può essere un simbolo di sottolineatura. *5*

Se l'utente che tenta di creare una base di dati non è autorizzato per questo, quello che si ottiene è un messaggio di errore del tipo seguente:

Connection to database 'template1' failed.
FATAL 1:SetUserId: user "tizio" is not in "pg_user"
createdb: database creation failed on mio_db.

161.4.2 Eliminazione di una base di dati

L'amministratore di una base di dati, generalmente colui che la ha creata, è la persona che può anche eliminarla. Nell'esempio seguente si elimina la base di dati mio_db.

destroydb mio_db

161.5 Accesso a una base di dati

L'accesso a una base di dati avviene attraverso un client, ovvero un programma frontale, o front-end, secondo la documentazione di PostgreSQL. Questo si avvale generalmente della libreria LIBPQ. PostgreSQL fornisce un programma client standard, psql, che si comporta come una sorta di shell tra l'utente e la base di dati stessa. *6*

Il programma psql permette un utilizzo interattivo attraverso una serie di comandi impartiti dall'utente su una riga di comando; oppure può essere avviato in modo da eseguire il contenuto di un file o di un singolo comando fornito tra gli argomenti. Per quanto riguarda l'utilizzo interattivo, il modo più semplice di essere avviato è quello che si vede nell'esempio seguente, dove si indica semplicemente il nome della base di dati sulla quale intervenire.

psql mio_db[Invio]

Welcome to the POSTGRESQL interactive sql monitor:
  Please read the file COPYRIGHT for copyright terms of POSTGRESQL

   type \? for help on slash commands
   type \q to quit
   type \g or terminate with semicolon to execute query
 You are currently connected to the database: mio_db

mio_db=>_

Da questo momento si possono inserire le istruzioni SQL per la base di dati selezionata, in questo caso mio_db, oppure si possono inserire dei comandi specifici di psql. Questi ultimi si notano perché sono composti da una barra obliqua inversa (\), seguita da un carattere.

Il comando interno di psql più importante è \h che permette di visualizzare una guida rapida alle istruzioni SQL che possono essere utilizzate.

=> \h[Invio]

type \h <cmd> where <cmd> is one of the following:
    abort                    abort transaction        alter table
    begin                    begin transaction        begin work
    cluster                  close                    commit
...
type \h * for a complete description of all commands

Nello stesso modo, il comando \? fornisce un riepilogo dei comandi interni di psql.

=> \?[Invio]

 \?           -- help
 \a           -- toggle field-alignment (currenty on)
 \C [<captn>] -- set html3 caption (currently '')
...

Tutto ciò che psql non riesce a interpretare come un suo comando interno viene trattato come un'istruzione SQL. Dal momento che queste istruzioni possono richiedere più righe, è necessario informare psql della conclusione di queste, per permettergli di analizzarle e inviarle al server. Queste istruzioni possono essere terminate con un punto e virgola (;), oppure con il comando \g.

Si può osservare, utilizzando psql, che l'invito mostrato cambia leggermente a seconda del contesto: inizialmente appare nella forma =>, mentre quando è in corso l'inserimento di un'istruzione SQL non ancora terminata si trasforma in ->. Il comando \g viene usato prevalentemente in questa situazione.

-\g[Invio]

Le istruzioni SQL possono anche essere raccolte in un file di testo normale. In tal caso si può utilizzare il comando \i per fare in modo che psql interpreti il suo contenuto, come nell'esempio seguente, dove il file in questione è mio_file.sql.

=> \i mio_file.sql[Invio]

Nel momento in cui si utilizza questa possibilità (quella di scrivere le istruzioni SQL in un file facendo in modo che poi questo venga letto e interpretato), diventa utile il poter annotare dei commenti. Questi sono iniziati da una sequenza di due trattini (--): tutto quello che vi appare dopo viene ignorato.

La conclusione del funzionamento di psql si ottiene con il comando \q.

=> \q[Invio]

161.5.1 $ psql

psql [<opzioni>] [<database>]

psql è un programma frontale (front-end) interattivo per l'invio di istruzioni SQL e l'emissione del risultato corrispondente. Si tratta di un client come gli altri, di conseguenza richiede la presenza di postmaster per instaurare una connessione con una copia del server postgres.

psql può funzionare in modo interattivo, come già accennato, oppure può eseguire le istruzioni contenute in un file. Questo può essere fornito attraverso l'opzione -f, oppure può provenire dallo standard input, attraverso una pipeline.

psql può funzionare solo in abbinamento a una base di dati determinata. In questo senso, se non viene indicato il nome di una base di dati nella riga di comando, psql tenta di utilizzarne una con lo stesso nome dell'utente. Per la precisione, si fa riferimento alla variabile di ambiente USER. *7*

Alcune opzioni

-c <istruzione-SQL>

Permette di fornire un'istruzione SQL già nella riga di comando, ottenendone il risultato attraverso lo standard output e facendo terminare subito dopo l'esecuzione di psql. Questa opzione viene usata particolarmente in abbinamento a -q.

-d <database>

Permette di indicare il nome della base di dati da utilizzare. Può essere utile quando per qualche motivo potrebbe essere ambigua l'indicazione del suo nome come ultimo argomento.

-f <file-di-istruzioni>

Permette di fornire a psql un file da interpretare contenente le istruzioni SQL (oltre agli eventuali comandi specifici di psql), senza avviare così una sessione di lavoro interattiva.

-h <host>

Permette di specificare il nodo a cui connettersi per l'interrogazione del server PostgreSQL.

-H

Fa in modo che l'emissione di tabelle avvenga utilizzando il formato HTML 3.0. In pratica, ciò è utile per costruire un risultato da leggere attraverso un navigatore web.

-o <file-output>

Fa in modo che tutto l'output venga inviato nel file specificato dall'argomento.

-p <porta>

Nel caso in cui postmaster sia in ascolto su una porta TCP diversa dal numero 5432 (corrispondente al valore predefinito), si può specificare con questa opzione il numero corretto da utilizzare.

-q

Fa in modo che psql funzioni in modo «silenzioso», limitandosi al puro output delle istruzioni impartite. Questa opzione è utile quando si utilizza psql all'interno di script che devono occuparsi di rielaborare il risultato ottenuto.

-t

Disattiva l'emissione dei nomi delle colonne. Questa opzione viene utilizzata particolarmente in abbinamento con -c o -q.

-T <opzioni-tabelle-html>

Questa opzione viene utilizzata in abbinamento con -H, per definire le opzioni HTML delle tabelle che si generano. In pratica, si tratta di ciò che può essere inserito all'interno del marcatore di apertura della tabella: <table ...>.

-u

Fa in modo che psql richieda il nominativo-utente e la password all'utente, prima di tentare la connessione. L'uso di questa opzione è indispensabile quando il server impone una forma di autenticazione definita attraverso la parola chiave password.

Alcuni comandi

Oltre alle istruzioni SQL, psql riconosce dei comandi, alcuni dei quali vengono descritti di seguito.

\h [<comando>]

L'opzione \h usata da sola, elenca le istruzioni SQL che possono essere utilizzate. Se viene indicato il nome di una di queste, viene mostrata in breve la sintassi relativa.

\?

Elenca i comandi interni di psql, cioè quelli che iniziano con una barra obliqua inversa (\).

\l

Elenca tutte le basi di dati presenti nel server. Ciò che si ottiene è una tabella contenente rispettivamente: i nomi delle basi di dati, i numeri UID dei rispettivi amministratori (gli utenti che li hanno creati), e il nome della directory in cui sono collocati fisicamente.

\connect <database> [<nome-utente>]

Chiude la connessione con la base di dati in uso precedentemente, e tenta di accedere a quella indicata. Se il sistema di autenticazione lo consente, si può specificare anche il nome dell'utente con cui si intende operare sulla nuova base di dati. Generalmente, ciò dovrebbe essere impedito. *8*

\d [<tabella>]

L'opzione \d usata da sola, elenca le tabelle contenute nella base di dati, altrimenti, se viene indicato il nome di una di queste tabelle, si ottiene l'elenco delle colonne. Se si utilizza il comando \d *, si ottiene l'elenco di tutte le tabelle con le informazioni su tutte le colonne rispettive.

\i <file>

Con questa opzione si fa in modo che psql esegua di seguito tutte le istruzioni contenute nel file indicato come argomento.

\q

Termina il funzionamento di psql.

Codici di uscita

Il programma psql può restituire i valori seguenti:

Esempi

psql mio_db

Cerca di connettersi con la base di dati mio_db nel nodo locale, utilizzando il meccanismo del socket di dominio UNIX.

psql -d mio_db

Esattamente come nell'esempio precedente, con l'uso dell'opzione -d che serve a evitare ambiguità sul fatto che mio_db sia il nome della base di dati.

psql -u -d mio_db

Come nell'esempio precedente, ma fa in modo che psql chieda all'utente il nominativo e la password da usare per collegarsi. È necessario usare questa opzione quando il servizio a cui ci si connette richiede un'autenticazione basata sull'uso di password.

psql -u -h dinkel.brot.dg -d mio_db

Come nell'esempio precedente, ma questa volta l'accesso viene fatto a una base di dati con lo stesso nome presso il nodo dinkel.brot.dg.

psql -f istruzioni.sql -d mio_db

Cerca di connettersi con la base di dati mio_db nel nodo locale, utilizzando il meccanismo del socket di dominio UNIX, e quindi esegue le istruzioni contenute nel file istruzioni.sql.

161.5.2 Variabile PAGER

psql è sensibile alla presenza o meno della variabile di ambiente PAGER. Se questa esiste, e non è vuota, psql userà il programma indicato al suo interno per controllare l'emissione dell'output generato. Per esempio, se contiene less, come si vede nell'esempio seguente che fa riferimento a una shell compatibile con quella di Bourne,

PAGER=less
export PAGER

si fa in modo che l'output troppo lungo venga controllato da less. Per eliminare l'impostazione di questa variabile, in modo da ritornare allo stato predefinito, basta annullare il contenuto della variabile nel modo seguente:

PAGER=
export PAGER

161.6 Manutenzione delle basi di dati

Un problema comune dei DBMS è quello della riorganizzazione periodica dei dati, in modo da semplificare e accelerare le elaborazioni successive. Nei sistemi più semplici si parla a volte di «ricostruzione indici», o di qualcosa del genere. Nel caso di PostgreSQL, si utilizza un comando specifico che è estraneo all'SQL standard: VACUUM. *9*

VACUUM [VERBOSE] [ANALYZE] [<nome-tabella>]

VACUUM [VERBOSE] ANALYZE [<nome-tabella> [(<colonna-1>[,... <colonna-N>])]]

L'operazione di pulizia si riferisce alla base di dati aperta in quel momento. L'opzione VERBOSE permette di ottenere i dettagli sull'esecuzione dell'operazione; ANALYZE serve invece per indicare specificatamente una tabella, o addirittura solo alcune colonne di una tabella.

Anche se non si tratta di un comando SQL standard, per PostgreSQL è importante che venga eseguita periodicamente una ripulitura attraverso il comando VACUUM, eventualmente attraverso uno script simile a quello seguente, da avviare per mezzo del sistema Cron.

#!/bin/sh
su postgres -c "psql $1 -c 'VACUUM'"

In pratica, richiamando questo script con i privilegi dell'utente root, indicando come argomento il nome della base di dati (viene inserito al posto di $1 dalla shell), si ottiene di avviare il comando VACUUM attraverso psql.

Per riuscire a fare il lavoro in serie per tutte le basi di dati, si potrebbe scrivere uno script più complesso, come quello seguente. In questo caso, lo script deve essere avviato con i privilegi dell'utente postgres.

#!/bin/sh

BASI_DATI=`psql template1 -t -c "SELECT datname from pg_database"`

echo "Procedimento di ripulitura e sistemazione delle basi di dati"
echo "di PostgreSQL."
echo "Se l'operazione dovesse essere interrotta accidentalmente,"
echo "potrebbe essere necessaria l'eliminazione del file pg_vlock"
echo "contenuto nella directory della base di dati relativa."

for BASE_DATI in $BASI_DATI
do
    echo -n "$BASE_DATI: "
    psql $BASE_DATI -c "VACUUM"
done

In breve, si utilizza la prima volta psql in modo da aprire la base di dati template1 (quella fondamentale, che permette di intervenire sui cataloghi di sistema), e da lì accedere al catalogo pg_database, in modo da leggere la colonna contenente i nomi delle basi di dati. In particolare, l'opzione -t serve a evitare di inserire il nome della colonna stessa. L'elenco che si ottiene viene inserito nella variabile di ambiente BASI_DATI, che in seguito viene scandita da un ciclo for, all'interno del quale si utilizza psql per ripulire ogni singola base di dati.

161.7 Maneggiare i file delle basi di dati

All'inizio del capitolo si è accennato alla collocazione normale delle directory e dei file che compongono le basi di dati. Chi amministra il sistema di elaborazione che ospita PostgreSQL e le basi di dati, deve avere almeno un'idea di come maneggiare questi file. Per esempio deve sapere come comportarsi per le copie di sicurezza, soprattutto come ripristinarle.

Per comodità, la directory da cui si articolano i cataloghi e le basi di dati verrà indicata come ~postgres/, ovvero la directory personale dell'utente postgres, cioè il DBA (l'amministratore delle basi di dati).

Quando si installa PostgreSQL si dovrebbe avere già una directory ~postgres/ organizzata in modo tale da poter iniziare a creare delle basi di dati. Per questo sono necessari alcuni file, detti cataloghi, e una base di dati di partenza: template1.

161.7.1 Cataloghi del DBMS

I cataloghi di PostgreSQL sono delle tabelle del DBMS che non appartengono ad alcuna base di dati e servono per gestire il DBMS stesso. Normalmente non si dovrebbe accedere a tali tabelle direttamente, ma solo tramite script o programmi specifici. Tuttavia ci sono situazioni in cui ciò potrebbe essere necessario, e comunque la documentazione di PostgreSQL fa spesso riferimento a queste, e quindi conviene almeno saperle consultare.

Dal momento che PostgreSQL consente di accedere a delle tabelle solo dopo avere specificato la base di dati, a queste si accede attraverso template1, in pratica attraverso un comando simile a quello seguente:

postgres:~$ psql -d template1

161.7.1.1 Catalogo pg_user

Il catalogo pg_user è una vista del catalogo pg_shadow, che contiene le informazioni sugli utenti di PostgreSQL. La figura 161.1 mostra un esempio di come potrebbe essere composta. La consultazione della tabella si ottiene con il comando SQL:

template1=> SELECT * FROM pg_user;

usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd  |valuntil
--------+--------+-----------+--------+--------+---------+--------+----------
postgres|     100|t          |t       |t       |t        |********|Sat Jan 31
nobody  |      99|f          |t       |f       |t        |********|
tizio   |    1001|t          |t       |t       |t        |********|

Figura 161.1: Esempio di un catalogo pg_user.

Si può osservare che l'utente postgres ha tutti gli attributi booleani attivi (usecreatedb, usetrace, usesuper, usecatupd), e questo per permettergli di compiere tutte le operazioni all'interno delle basi di dati. In particolare, l'attributo usecreatedb permette all'utente di creare una base di dati, e usesuper permette di aggiungere utenti. In effetti, osservando l'esempio della figura, l'utente tizio ha praticamente gli stessi privilegi dell'amministratore postgres.

161.7.1.2 Catalogo pg_shadow

Il catalogo pg_shadow è il contenitore delle informazioni sugli utenti, a cui si accede normalmente tramite la vista pg_user. Il suo scopo è quello di conservare in un file più sicuro (perché non è accessibile agli utenti comuni) i dati delle password degli utenti che intendono usare le forme di autenticazione basate su queste. Per il momento, nella documentazione di PostgreSQL non viene spiegato come usarlo, né se le password indicate devono essere in chiaro o cifrate in qualche modo. L'esempio della figura 161.2 mostra gli stessi utenti a cui non viene abbinata alcuna password. La consultazione della tabella si ottiene con il comando SQL:

template1=> SELECT * FROM pg_shadow;

usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd|valuntil
--------+--------+-----------+--------+--------+---------+------+----------
postgres|     100|t          |t       |t       |t        |      |Sat Jan 31
nobody  |      99|f          |t       |f       |t        |      |
tizio   |    1001|t          |t       |t       |t        |      |

Figura 161.2: Esempio di un catalogo pg_shadow.

161.7.1.3 Catalogo pg_database

Il catalogo pg_database è una tabella che contiene le informazioni sulle basi di dati esistenti. La figura 161.3 mostra un esempio di come potrebbe essere composta. La consultazione della tabella si ottiene con il comando SQL:

template1=> SELECT * FROM pg_database;

datname  |datdba|encoding|datpath
---------+------+--------+--------------------
template1|   100|       0|template1
pubblico |   100|       0|pubblico
prova    |   100|       0|/home/postgres/prova
prova1   |   100|       0|prova1
prova2   |  1001|       0|prova2

Figura 161.3: Esempio di un catalogo pg_database.

La prima colonna rappresenta il nome della base di dati, la seconda riporta il numero UID dell'utente che rappresenta il suo DBA, cioè colui che l'ha creata, la terza rappresenta il percorso in cui si trova. Per esempio, si può osservare che la base di dati prova2 è stata creata dall'utente 1001, che da quanto riportato in pg_user è tizio.

La colonna che rappresenta il percorso della base di dati è più complessa da interpretare. In generale, i nomi che appaiono senza l'indicazione di un percorso si riferiscono alla directory ~postgres/base/, e corrispondono in pratica alla directory che contiene i file della base di dati. Per esempio, la base di dati prova2 è collocata nella directory ~postgres/base/prova2/. I percorsi assoluti vanno interpretati in modo speciale, e forse conviene cercare di capirlo intuitivamente, chiarendo che nel caso della base di dati prova, la directory corrispondente è in realtà /home/postgres/base/prova/ (si osservi l'inserzione di base/).

In generale, è normale che tutte le basi di dati vengano create a partire da ~postgres/base/, e quindi non si dovrebbero vedere percorsi assoluti in questa tabella. Verrà mostrato in seguito quando può verificarsi questa condizione.

161.7.2 Copia e spostamento di una base di dati

Prima di poter pensare a copiare o a spostare una base di dati occorre avere chiaro in mente che si tratta di file «binari» (nel senso che non si tratta di file di testo), contenenti informazioni collegate l'una all'altra in qualche modo più o meno oscuro. Queste informazioni possono a volte essere espresse anche in forma numerica, e in tal caso dipendere dall'architettura in cui sono state create. Questo implica due cose fondamentali: lo spostamento o la copia deve essere fatto in modo che non si perdano dei pezzi per la strada (i file della stessa base di dati devono essere raccolti tutti assieme), e lo spostamento in un'altra architettura non dovrebbe essere ammissibile.

La copia di una base di dati per motivi di sicurezza è un'operazione semplice, e così anche il suo ripristino. Si tratta di archiviare, e poi eventualmente ripristinare, tutto il contenuto della directory che la contiene. Per esempio,

tar czvf base.tar.gz ~postgres/base

archivia nel file base.tar.gz tutte le basi di dati che si articolano a partire da ~postgres/base/. Come esempio ulteriore,

tar czvf pubblico.tar.gz ~postgres/base/pubblico

archivia nel file pubblico.tar.gz solo la base di dati pubblico, che si trova esattamente nella directory ~postgres/base/pubblico/.

Il recupero non è nulla di speciale, tranne per il fatto che si deve recuperare una base dati per intero, ovvero ciò che di solito si articola in una sottodirectory di ~postgres/base/. Se di dovessero perdere informazioni sui permessi, occorre ricordare che i file devono appartenere all'utente postgres, ovvero colui che rappresenta l'amministratore del DBMS.

Per poter spostare una base di dati nel filesystem occorre ricordare che l'informazione sulla sua collocazione è contenuta nel catalogo pg_database, ed è su questo che occorre intervenire per informare PostgreSQL della nuova posizione che gli si vuole dare. Eventualmente, c'è sempre la possibilità di eliminare la base di dati con il comando destroydb, e di ricrearla nella nuova posizione, sostituendo poi tutti i file con quella vecchia. In pratica, all'interno dei file che compongono una base di dati non c'è l'informazione della loro collocazione, quindi, a parte il problema di modificare in qualche modo il catalogo pg_database, non si dovrebbero incontrare altre difficoltà.

Per salvare tutto il sistema di basi di dati di PostgreSQL, si può agire in modo più semplice archiviando tutta la directory ~postgres/, in modo ricorsivo. In questo senso, se ci sono delle basi di dati che risiedono al di fuori della gerarchia ~postgres/, le cose si complicano, e questo spiega il motivo dell'organizzazione standard di PostgreSQL che prevede la loro collocazione al di sotto della gerarchia ~postgres/base/. Nel caso non fosse ancora chiaro, è bene ribadire che salvando anche i file che risiedono esattamente nella directory ~postgres/, si evita di dover ricreare le basi di dati prima del loro recupero, ovvero si evita di dover intervenire manualmente nei cataloghi per dichiararne la presenza.

161.7.3 Creazione di una base di dati in una collocazione diversa dalla solita

Il comando createdb, se non viene specificato diversamente, crea la base di dati in una sottodirectory a partire da ~postgres/base/. Se si vuole definire una nuova posizione basta usare l'opzione -D, seguita dalla directory che deve essere presa in considerazione al posto di ~postgres/ (ovvero di PGDATA come si legge nella documentazione di PostgreSQL).

Perché la cosa funzioni, occorre che la directory ricevente sia pronta. Per esempio, volendo creare la base di dati mia a partire da /home/postgresql/, sapendo che poi in pratica la sottodirectory mia/ viene collocata su /home/postgresql/base/, occorre predisporre tutto questo.

mkdir /home/postgresql

mkdir /home/postgresql/base

chown -R postgres. /home/postgresql

La preparazione delle directory può essere fatta con l'aiuto di initlocation, ma questo comando non fa niente di particolare in più. Per completare l'esempio, viene mostrato il comando con cui si crea la base di dati mia, utilizzando come riferimento la directory /home/postgresql.

postgres:~$ createdb -D /home/postgresql mia

Per concludere, se si osserva il catalogo pg_database, si noterà che il percorso indicato della base di dati appena creata è /home/postgresql/mia/, mentre invece la directory vera e propria è /home/postgresql/base/mia/.

161.7.4 Copia e spostamento di una base di dati, in modo indipendente dalla piattaforma

Dopo aver visto in che modo è possibile copiare e archiviare una base di dati, rimanendo sulla stessa piattaforma, e soprattutto, rimanendo nell'ambito della stessa versione di PostgreSQL, è necessario vedere in che modo si può risolvere il problema quando la piattaforma cambia, o quando cambia la versione di PostgreSQL.

Ricapitolando, quindi, i problemi sono due: la piattaforma e la versione di PostgreSQL. In linea di principio, non è possibile copiare una base di dati realizzata su GNU/Linux in una macchina i386 per portarla in un'altra macchina con architettura differente, anche se con lo stesso sistema operativo; nemmeno si può trasportare una base di dati, così come si trova, da un sistema operativo a un altro. Inoltre, PostgreSQL non è in grado di leggere, o di utilizzare in alcun modo, le basi di dati realizzate con altre versioni dello stesso.

Attualmente, l'unico modo per raggirare l'ostacolo è lo scarico dei dati (dump) in uno script che successivamente può essere dato in pasto a psql, per ricreare le basi di dati come erano in origine. Naturalmente, questa tecnica non è perfetta, e funziona correttamente solo quando le basi di dati non contengono relazioni con tuple eccessivamente grandi.

Questo problema deve essere preso in considerazione già nel momento della progettazione di una base di dati, avendo cura di verificare, sperimentandolo, che il procedimento di scarico e recupero dei dati possa funzionare.

Lo scarico di una base di dati si ottiene attraverso il programma pg_dump, che è parte integrante della distribuzione di PostgreSQL.

pg_dump [<opzioni>] <base-di-dati>

Se non si indicano delle opzioni, e ci si limita a specificare la base di dati su cui intervenire, si ottiene il risultato attraverso lo standard output, composto in pratica dai comandi necessari a psql per ricostruire le relazioni che compongono la base di dati (la base di dati stessa deve essere ricreata manualmente). Tanto per chiarire subito il senso della cosa, se si utilizza pg_dump nel modo seguente,

pg_dump mio_db > mio_db.dump

si ottiene il file di testo mio_db.dump. Questo file va verificato alla ricerca di segnalazioni di errore che potrebbero essere generate in presenza di dati che non possono essere riprodotti fedelmente, ed eventualmente, può essere modificato se si conosce la sintassi dei comandi che vengono inseriti in questo script. Per fare in modo che le relazioni della base di dati vengano ricreate e caricate, si può utilizzare psql nel modo seguente:

psql -e mio_db < mio_db.dump

Alcune opzioni

-d

In condizioni normali, pg_dump salva i dati delle relazioni (le tabella secondo l'SQL) in una forma compatibile con il comando COPY che non è compatibile con lo standard SQL. Con l'opzione -d, utilizza il comando INSERT tradizionale.

-D

Come con l'opzione -d, con l'aggiunta dell'indicazione degli attributi (le colonne secondo l'SQL) in cui vanno inseriti i dati. In pratica, questa opzione permette di generare uno script più preciso e dettagliato.

-f <file>

Permette di definire un file diverso dallo standard output, che si vuole generare con il risultato dell'elaborazione di pg_dump.

-h <host>

Permette di specificare il nodo a cui connettersi per l'interrogazione del server PostgreSQL. In pratica, se l'accesso è consentito, è possibile scaricare una base di dati gestita presso un nodo remoto.

-p <porta>

Nel caso in cui postmaster sia in ascolto su una porta TCP diversa dal numero 5432 (corrispondente al valore predefinito), si può specificare con questa opzione il numero corretto da utilizzare.

-s

Scarica soltanto la struttura delle relazioni, senza occuparsi del loro contenuto. In pratica, serve per poter riprodurre vuote le tabelle SQL.

-t <nome-tabella>

Utilizzando questa opzione, indicando il nome di una tabella SQL, si ottiene lo scarico di quell'unica tabella.

-u

Fa in modo che psql richieda il nominativo-utente e la password all'utente, prima di tentare la connessione. L'uso di questa opzione è indispensabile quando il server impone una forma di autenticazione definita attraverso la parola chiave password.

-z

Include le informazioni sui permessi e la proprietà delle tabelle (GRANT/REVOKE).

161.7.5 Copia, spostamento e aggiornamento di tutte le basi di dati, in modo indipendente dalla piattaforma

Per copiare o trasferire tutte le basi di dati del sistema di PostgreSQL, si può utilizzare pg_dumpall, che in pratica è uno script che si avvale di pg_dump per compiere il suo lavoro.

pg_dumpall [<opzioni>]

pg_dumpall provvede a scaricare tutte le basi di dati, assieme alle informazioni necessarie per ricreare il catalogo pg_shadow (la vista pg_user si ottiene di conseguenza). Come si può intuire, si deve utilizzare pg_dumpall con i privilegi dell'utente postgres.

Gli argomenti della riga di comando di pg_dumpall, vengono passati tali e quali a pg_dump, quando questo viene utilizzato all'interno dello script per lo scarico di ogni singola base di dati.

postgres$ pg_dumpall > basi_dati.dump

L'esempio mostra il modo più semplice di utilizzare pg_dumpall per scaricare tutte le basi di dati in un unico file. In questo caso, si ottiene il file di testo basi_dati.dump. Questo file va verificato alla ricerca di segnalazioni di errore che potrebbero essere generate in presenza di dati che non possono essere riprodotti fedelmente, ed eventualmente, può essere modificato se si conosce la sintassi dei comandi che vengono inseriti in questo script.

Il recupero dell'insieme completo delle basi di dati avviene normalmente in un'ambiente PostgreSQL, in cui il sistema delle basi di dati sia stato predisposto, ma non sia stata creata alcuna base di dati (a parte template1 la cui presenza è obbligatoria). Come si può intuire, il comando necessario per ricaricare le basi di dati, assieme alle informazioni sugli utenti (il catalogo pg_shadow), è quello seguente:

postgres$ psql -e template1 < basi_dati.dump

La situazione tipica in cui è necessario utilizzare pg_dumpall per scaricare tutto il sistema delle basi di dati, è quella del momento in cui ci si accinge ad aggiornare la versione di PostgreSQL. In breve, in quella occasione, si devono eseguire i passaggi seguenti:

  1. con la versione vecchia di PostgreSQL, si deve utilizzare pg_dumpall in modo da scaricare tutto il sistema delle basi di dati in un unico file di testo;

  2. si aggiorna PostgreSQL;

  3. si elimina il contenuto della directory ~postgres/, ovvero quella che altrimenti viene definita PGDATA (prima conviene forse fare una copia di sicurezza);

  4. si ricrea il sistema delle basi di dati, vuoto, attraverso initdb;

  5. si ricaricano le basi di dati precedenti, assieme alle informazioni sugli utenti, attraverso psql, utilizzando il file generato in precedenza attraverso pg_dumpall.

Quello che manca, di solito si tratta del file ~postgres/pg_hda.conf per la configurazione dei sistemi di accesso e autenticazione, deve essere ripristinato manualmente.

161.8 Riferimenti

---------------------------

Appunti Linux 1999.09.21 --- Copyright © 1997-1999 Daniele Giacomini --  daniele @ pluto.linux.it


1.) Probabilmente, la scelta del nome «postmaster» è un po' infelice, dal momento che potrebbe far pensare all'amministratore del servizio di posta elettronica. Come al solito occorre un po' di attenzione al contesto in cui ci si trova.

2.) Per consentire in pratica l'accesso attraverso la rete, occorre anche intervenire all'interno del file di configurazione ~postgres/pg_hda.conf.

3.) L'autenticazione IDENT prevede anche l'uso di un file di mappa aggiuntivo, che viene preso in considerazione quando al posto della parola chiave sameuser si indica qualcosa d'altro. Tuttavia, la documentazione sul modo in cui debba essere predisposto questo file non è disponibile allo stato attuale.

4.) In ogni caso, la copia da sola non basta. Perché una base di dati sia riconosciuta come tale occorre che questa sia stata annotata nel file ~postgres/pg_database.

5.) La dimensione massima dei nomi dipende dal modo in cui sono stati compilati i sorgenti o dalle caratteristiche della piattaforma. Il limite di 16 caratteri è sufficientemente basso da andare bene in ogni circostanza.

6.) Il programma client tipico, dovrebbe riconoscere le variabili di ambiente PGHOST e PGPORT. La prima serve a stabilire l'indirizzo o il nome di dominio del server, e questo implica che la connessione avviene attraverso una connessione TCP, e non con un socket di dominio UNIX; la seconda specifica il numero della porta, ammesso che si voglia utilizzare un numero diverso da 5432. L'uso di queste variabili non è indispensabile, ma serve solo per non dover specificare queste informazioni attraverso opzioni della riga di comando.

7.) Questo dettaglio dovrebbe permettere di comprendere il significato della segnalazione di errore che si ottiene se si tenta di avviare psql senza indicare una base di dati, quando non ne esiste una con lo stesso nome dell'utente.

8.) Se si utilizza un'autenticazione basata sul file pg_hba.conf, l'autenticazione di tipo trust consente questo cambiamento di identificazione, altrimenti, il tipo ident lo impedisce. La configurazione normale prevede che il nodo locale (127.0.0.1) possa accedere con un'autenticazione di tipo trust, e ciò permette di cambiare il nome dell'utente in questo comando.

9.) Per comprendere bene il contenuto di questa sezione, può essere necessaria la lettura del prossimo capitolo. Queste informazioni sono collocate qui soltanto per una questione di ordine logico nella posizione delle stesse.


[inizio] [indice generale] [precedente] [successivo] [indice analitico] [contributi]