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


190. 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.

190.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/'.

190.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.

190.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.

190.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.

190.2 Impostazione cliente-servente e amministrazione

Il DBMS di PostgreSQL si basa su un sistema cliente-servente, in cui, il programma che vuole interagire con una base di dati determinata deve farlo attraverso delle richieste inviate a un servente. 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 servente vero e proprio (back-end), a cui affida la connessione con il cliente. Il demone in ascolto per le richieste di nuove connessioni è `postmaster', mentre il servente è `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 clienti sono connessi, si può osservare una dipendenza del tipo rappresentato dallo schema seguente:

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

190.2.1 # postmaster

postmaster [<opzioni>]

`postmaster' è il demone che si occupa di restare in ascolto in attesa di una richiesta di connessione con un servente `postgres' (il programma terminale, o back-end in questo contesto). Quando riceve questo tipo di richiesta mette in connessione il cliente (o front-end) con una nuova copia del servente `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-programma-terminale>

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

-d [<livello-di-diagnosi>]

Questa opzione permette di attivare la segnalazione di messaggi diagnostici (debug), da parte di `postmaster' e da parte dei programmi terminali, a più livelli di dettaglio:

  • 1, segnala solo il traffico di connessione;

  • 2, o superiore, attiva la segnalazione diagnostica anche nei programmi terminali, oltre ad aggiungere dettagli sul funzionamento di `postmaster'.

Di norma, i messaggi diagnostici vengono emessi attraverso lo standard output da parte di `postmaster', anche quando si tratta di messaggi provenienti dai programmi terminali. 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.

190.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 servente, ovvero al sistema di gestione dei dati, e non al cliente. 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 190.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 190.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

190.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.

190.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]

190.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 219). 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.

190.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 clienti 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 clienti 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.

190.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 cliente 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 cliente 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]

190.4 Configurazione nella distribuzione GNU/Linux Debian

La distribuzione GNU/Linux Debian è molto attenta alla coerenza dei pacchetti che si installano, e nel caso di PostgreSQL, può essere controllato tutto a partire dai file che si trovano nella directory `/etc/postgresql/'. In particolare, si trova in questa directory il file `pg_hba.conf' che è già stato descritto in precedenza; e in particolare, si trova un file aggiuntivo che viene interpretato dallo script della procedura di inizializzazione del sistema che si occupa di avviare e di arrestare il servizio. Si tratta del file `/etc/postgresql/postmaster.init', attraverso il quale si possono controllare tante piccole cose, che altrimenti andrebbero controllate attraverso le opzioni della riga di comando del demone relativo.

# /etc/postgresql/postmaster.init
#
# Copyright (c) Oliver Elphick 1997
# Part of the Debian package, postgresql. The Debian packaging is
# licensed under GPL v.2
#
# This is the configurable initialisation of the postgresql package
# The defaults are shown, but are commented out.
#
POSTGRES_HOME=`grep '^postgres:' /etc/passwd | awk -F: '{print $6}'`
if [ -z "$POSTGRES_HOME" ]
then
    POSTGRES_HOME=/var/postgres
fi

# Where to find the PostgreSQL database files, including those that
# define PostgreSQL users and permissions.
# POSTGRES_DATA=/var/postgres/data

# Where to send logging and debugging traces
# POSTGRES_LOG=/var/log/postgres.log

# The number of shared-memory buffers the postmaster is
# to allocate for backend server processes.  Each buffer is 8Kb.
# PGBUFFERS=64

# Debugging level at which the backend servers are to operate.
# 1: trace connection traffic only; >=2: turn on debugging in the backends
# giving more information according to the debug level. Debug logs are
# sent to $POSTGRES_LOG
# PGDEBUG=0

# Whether to echo queries to the debug log: yes/no
# PGECHO=no

# Whether to disable the fsync() call after each transaction. (If fsync() is
# disabled, performance will improve at the cost of an increased risk of data
# corruption in the event of power or other hardware failure.): yes/no
# PGFSYNC=yes

# How to present dates to the frontend. The choices are American (mm-dd-yyyy)
# or European (dd-mm-yyyy)
# PGDATESTYLE=European

# How much memory to use for internal sorts before resorting to the disk.
# This value is in kilobytes.
# PGSORTMEM=512

# Whether to print timing and other statistics after each query: yes/no
# PGSTATS=no

# Whether to allow connections through TCP/IP as well as through Unix
# sockets: yes/no.
# By default, for greater security, we do not allow TCP/IP access.
# This means that only users on this machine can access the database.
PGALLOWTCPIP=yes

# The Internet TCP port on which postmaster is to listen for connections
# from frontend applications.
# PGPORT=5432

# Locale setting for the postmaster and backend to use: this is not
# necessary for USA users, but most others will probably want to set it; it
# controls things like the format of numbers and dates.
# for example, use `LANG=en_GB' for British English.
LANG=it_IT

Quello che si vede è l'esempio del file predefinito con alcuni ritocchi per adattarlo alle particolarità locali. È importante sottolineare che per motivi di sicurezza, l'accesso tramite la rete viene impedito inizialmente, per cui occorre abilitare la cosa in modo esplicito, attraverso la direttiva `PGALLOWTCPIP=yes', come si vede dall'esempio stesso.

190.5 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.

190.5.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.

190.5.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

190.6 Accesso a una base di dati

L'accesso a una base di dati avviene attraverso un cliente, ovvero un programma frontale, o front-end, secondo la documentazione di PostgreSQL. Questo si avvale generalmente della libreria `LIBPQ'. PostgreSQL fornisce un programma cliente 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 solo 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 servente. 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]

190.6.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 cliente come gli altri, di conseguenza richiede la presenza di `postmaster' per instaurare una connessione con una copia del servente `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 servente 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 servente 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 servente. 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:

  • 0 se tutte le istruzioni sono state eseguite senza errori;

  • 1 se si sono verificati errori;

  • 2 se è intervenuta una disconnessione da parte del servente sottostante.

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'.

190.6.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

190.7 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 <ttid>base di dati</ttid> 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.

190.8 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'.

190.8.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

190.8.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 190.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 190.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'.

190.8.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 190.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 190.2: Esempio di un catalogo `pg_shadow'.

190.8.1.3 Catalogo pg_database

Il catalogo `pg_database' è una tabella che contiene le informazioni sulle basi di dati esistenti. La figura 190.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 190.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.

190.8.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.

190.8.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/'.

190.8.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 servente 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 servente impone una forma di autenticazione definita attraverso la parola chiave `password'.

-z

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

190.8.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 file unico. 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 solo 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.

190.9 Riferimenti

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

Appunti Linux 2000.04.12 --- Copyright © 1997-2000 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 cliente tipico, dovrebbe riconoscere le variabili di ambiente `PGHOST' e `PGPORT'. La prima serve a stabilire l'indirizzo o il nome di dominio del servente, 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]