[successivo] [precedente] [inizio] [fine] [indice generale] [violazione licenza] [translators] [docinfo] [indice analitico] [volume] [parte]


Capitolo 389.   PostgreSQL: struttura e preparazione

PostgreSQL (1) è 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.

389.1   Struttura dei dati nel file system

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 iniziale 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/.

389.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, 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.

389.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, corrispondente di solito all'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 parola d'ordine dovrebbe essere «impossibile», come nell'esempio seguente:

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

Come si vede, il campo della parola d'ordine è 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[Invio]

Nel secondo caso, l'attribuzione di una parola d'ordine all'utente postgres permette a una persona diversa di amministrare il DBMS.

passwd postgres[Invio]

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

389.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ò potrebbe risiedere al di fuori dei percorsi normali contenuti nella variabile $PATH; precisamente potrebbe trattarsi della directory /usr/lib/postgresql/bin/.

[percorso]initdb [opzioni] [--pgdata=directory |-D directory]

Lo schema sintattico mostra in modo molto semplice l'uso di initdb. Se si definisce correttamente la variabile di ambiente PGDATA, si può fare anche a meno delle opzioni, diversamente diventa necessario dare questa informazione attraverso l'opzione -D.

Volendo fare tutto da zero, occorre predisporre la directory iniziale di proprietà dell'utente fittizio postgres:

mkdir ~postgres[Invio]

chown postgres: ~postgres[Invio]

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

su postgres[Invio]

Successivamente, si deve avviare initdb specificando la directory a partire dalla quale si devono articolare i file che costituiscono le basi di dati. La directory in questione è normalmente ~postgres/data/:

postgres$ /usr/lib/postgresql/bin/initdb --locale=it_IT --encoding=UNICODE \
  \--pgdata=~postgres/data
[Invio]

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale it_IT.
This locale setting will prevent the use of indexes for pattern matching
operations.  If that is a concern, rerun initdb with the collation order
set to "C".  For more information see the Administrator's Guide.

creating directory /var/lib/postgres/data... ok
creating directory /var/lib/postgres/data/base... ok
creating directory /var/lib/postgres/data/global... ok
creating directory /var/lib/postgres/data/pg_xlog... ok
creating directory /var/lib/postgres/data/pg_clog... ok
creating template1 database in /var/lib/postgres/data/base/1... ok
creating configuration files... ok
initializing pg_shadow... ok
enabling unlimited row size for system tables... ok
initializing pg_depend... ok
creating system views... ok
loading pg_description... ok
creating conversions... ok
setting privileges on built-in objects... ok
vacuuming database template1... ok
copying template1 to template0... ok

Success. You can now start the database server using:

    /usr/lib/postgresql/bin/postmaster -D /var/lib/postgres/data
or
    /usr/lib/postgresql/bin/pg_ctl -D /var/lib/postgres/data -l logfile start

Nell'esempio sono state usate anche due opzioni il cui significato dovrebbe risultare intuitivo.

Tabella 389.1. Alcune opzioni per l'uso di initdb.

Opzione Descrizione

--pgdata=directory_pgdata

-D directory_pgdata

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

--locale=sigla_locale

Stabilisce la configurazione locale. Se non viene utilizzata questa opzione si usa il contenuto delle variabili di ambiente LANG ed eventualmente LC_*.

--encoding=codifica

-E codifica

Stabilisce la codifica della base di dati usata come modello (templaten) e di conseguenza la codifica predefinita per le nuove basi di dati. Tra le varie sigle che si possono usare vale la pena di menzionare UNICODE, SQL_ASCII.

Teoricamente, initdb fa tutto quello che è necessario fare; in pratica potrebbe non essere così. La prima cosa da considerare sono i file di configurazione, che, seguendo l'esempio mostrato, vengono collocati nella directory ~postgres/data/. Molto probabilmente la propria distribuzione GNU è organizzata per avere i file di configurazione in una directory /etc/postgresql/, o simile. Se le cose stanno così, bisogna provvedere a sostituire i file di configurazione nella directory ~postgres/data/ con dei collegamenti simbolici appropriati.

Le distribuzioni GNU possono avere la necessità di passare alcune informazioni, tramite variabili di ambiente, all'utente fittizio postgres, cosa che si ottiene con un file ~postgres/.profile appropriato. Se si vuole ricreare la directory ~postgres/ da zero, ma si nota la presenza di file di configurazione della shell, è necessario accertarsi del loro contenuto e provvedere di conseguenza nella ricostruzione della directory.

Un'ultima questione importante da sistemare è la directory ~postgres/dumpall/, che serve a contenere versioni vecchie degli eseguibili di PostgreSQL, con lo scopo di recuperare i dati dalle versioni vecchie delle basi di dati. Normalmente è sufficiente recuperare la directory già usata in precedenza.

389.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, che di solito corrisponde al numero 5 432). 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.

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.

Generalmente, il demone postmaster viene avviato attraverso la procedura di inizializzazione del sistema, in modo indipendente dal supervisore dei servizi di rete. In pratica, di solito si utilizza uno script collocato all'interno di /etc/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

389.2.1   Avvio del servente

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, assieme ai 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.

Opzione Descrizione

-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, 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 (5 432).

Segue la descrizione di alcuni esempi.

389.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, mentre ciò non serve dalla parte del 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, senza poter 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, per cui 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 viene 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 un'altra simile, 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 389.3 elenca le parole chiave che si possono assegnare a questa variabile e l'effetto che ne deriva.

Tabella 389.3. Elenco dei formati di data gestibili con PostgreSQL.

Stile Descrizione Esempio
ISO ISO 8601 2007-12-31
SQL Tipo tradizionale 12/31/2007
German 31.12.2007

Normalmente la cosa migliore è utilizzare il formato ISO, che potrebbe anche essere quello predefinito. 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

389.2.3   File di configurazione del servente

Come è stato descritto fino a questo punto, è possibile influenzare il comportamento del servente PostgreSQL attraverso opzioni della riga di comando e variabili di ambiente. Oltre a questi metodi, è possibile intervenire nel file ~postgres/postgresql.conf, attraverso direttive che assomigliano all'assegnamento di variabili. Il loro significato dovrebbe risultare intuitivo. Viene mostrato un esempio completo di questo file:

#
# PostgreSQL configuration file
# -----------------------------
#
# This file consists of lines of the form
#
#   name = value
#
# (The `=' is optional.) White space is collapsed, comments are
# introduced by `#' anywhere on a line. The complete list of option
# names and allowed values can be found in the PostgreSQL
# documentation. Examples are:

#log_connections = on
#fsync = off
#max_connections = 64

# Any option can also be given as a command line switch to the
# postmaster, e.g., 'postmaster -c log_connections=on'. Some options
# can be set at run-time with the 'SET' SQL command.

# See /usr/share/doc/postgresql/README.postgresql.conf.gz for a full list
# of the allowable options

debug_level = 0
log_connections = on
log_pid = on
log_timestamp = on
syslog = 2
# if syslog is 0, turn silent_mode off!
silent_mode = off
syslog_facility = LOCAL0
trace_notify = off
max_connections = 64
# shared_buffers must be at least twice max_connections, and not less than 16
shared_buffers = 128
# TCP/IP access is allowed by default, but the default access given in
# pg_hba.conf will permit it only from localhost, not other machines.
tcpip_socket = 1

Si può osservare la direttiva tcpip_socket = 1, che abilita l'accesso al servente attraverso la rete.

389.2.4   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---> tizio[Invio]

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

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

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

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

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

All'utente non viene concesso di aggiungere altri utenti.

createuser: tizio 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 ---> tizio[Invio]

destroyuser: delete of user tizio 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.

389.2.5   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]

389.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 iniziale 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), cosa che 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 parola d'ordine agli utenti di PostgreSQL. Queste parole d'ordine 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 viene ripreso in seguito).

Inoltre, l'autenticazione può avvenire attraverso un sistema Kerberos, oppure attraverso il protocollo IDENT (capitolo 211). In questo 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.

389.3.1   Configurazione

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 base_di_dati autenticazione_utente [mappa]

host base_di_dati 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).

Tabella 389.4. Parole chiave che possono essere usate nel campo autenticazione_utente.

Autenticazione Descrizione

trust

L'autenticazione non ha luogo e si accetta il nome fornito dall'utente senza alcuna verifica.

reject

La connessione viene rifiutata in ogni caso.

password

Viene richiesta una parola d'ordine riferita all'utente, verificandola in base al contenuto di un file indicato nel campo successivo, oppure in base a quanto riportato dal catalogo ~postgres/pg_shadow.

crypt

Viene richiesta una parola d'ordine riferita all'utente, verificandola in base al contenuto di ~postgres/pg_shadow. La differenza più importante rispetto a password sta nel fatto che in quel caso la parola d'ordine viene trasmessa in chiaro, mentre con crypt no.

ident

L'autenticazione avviene attraverso il protocollo IDENT (capitolo 211), demandando il riconoscimento al sistema remoto.
Si intende che questo metodo sia anche molto poco sicuro.

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 parola d'ordine, 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.

389.3.2   Gestione delle parole d'ordine 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 parole d'ordine cifrate relative. Per esempio, nel file ~postgres/pg_hba.conf potrebbe comparire il record seguente:

host    nostro_db       192.168.0.0     255.255.0.0     password  utenti

In tal caso, gli utenti che accedono attraverso un cliente avviato dai nodi della sottorete 192.168.*.* devono identificarsi attraverso l'indicazione di una parola d'ordine 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 parola d'ordine. Quando si usa il programma psql che viene descritto in seguito, occorre specificare l'opzione -u.

La parola d'ordine 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 parola d'ordine 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 sempronio (è importante ricordare di operare in qualità di utente postgres).

cd ~postgres[Invio]

su postgres[Invio]

postgres:~$ pg_passwd utenti[Invio]

Username: sempronio[Invio]

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

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

389.4   Configurazione nella distribuzione GNU/Linux Debian

La distribuzione GNU/Linux Debian è molto attenta alla coerenza dei pacchetti che si installano; pertanto, 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 e il file postgresql.conf che sono già stati descritti in precedenza; inoltre, 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 dei file /etc/postgresql/postmaster.conf, attraverso il quale si possono controllare delle piccole cose a cui non si può accedere con il file postgresql.conf, che altrimenti richiederebbero di intervenire attraverso le opzioni della riga di comando del demone relativo.

# /etc/postgresql/postmaster.conf
#
# Copyright (c) Oliver Elphick 1997, 2001
# 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.
#
# As of release 7.1, many parameters may now be found in
# /etc/postgresql/postgresql.conf.  To avoid confusion, these can
# no longer be set here, even though the command line options that
# used to control them do still exist.
#

POSTGRES_HOME=`getent passwd postgres | awk -F: '{print $6}' | head -1`
if [ -z "$POSTGRES_HOME" ]
then
    POSTGRES_HOME=/var/lib/postgres
fi

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

# Where to send logging and debugging traces.  By default, very little
# should appear here, because SYSLOG is set to 2 in postgresql.conf, so
# that all messages are sent to syslog only.
# POSTGRES_LOG=/var/log/postgres.log

# How (by default) to present dates to the frontend; the user can override
# this setting for his own session. The choices are:
#   Style      Date            Date-time
#   ----------------------------------------------------------------
#   ISO        1999-07-17      1999-07-17 07:09:18+01
#   SQL        17/07/1999      17/07/1999 07:09:19.00 BST
#   POSTGRES   17-07-1999      Sat 17 Jul 07:09:19 1999 BST
#   GERMAN     17.07.1999      17.07.1999 07:09:19.00 BST
#
# It is also possible to specify month-day or day-month ordering in date
# input and output.  Americans tend to use month-day; Europeans use
# day-month.  Specify European or nonEuropean. Separate the two parameters
# by a comma with no spaces
# PGDATESTYLE=ISO,European

# Any special options to pass to the postmaster through pg_ctl's -o option.
# This may include such options as "-h hostname", for which there is no
# parameter defined.  However most options can be set by editing
# postgresql.conf appropriately.  
POSTMASTER_OPTIONS=""

# Minimum number of entries in the kernel file table.  If the table size is
# lower, postgresql.startup attempts to increase it by writing this parameter 
# into /proc/sys/kernel/file-max.  This is only effective if the kernel has
# been compiled to support run-time configuration.
# KERNEL_FILE_MAX=1032

389.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 dropdb, 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.

389.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/.

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.

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[Invio]

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 trattino basso.

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.

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.

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

dropdb mio_db[Invio]

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

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, indicando implicitamente 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 5 432. L'uso di queste variabili non è indispensabile, ma serve solo per non dover specificare queste informazioni attraverso opzioni della riga di comando.

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 per avviarlo è 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]

Il programma cliente 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 [opzioni] [base_di_dati]

psql -f file_di_istruzioni [altre_opzioni] [base_di_dati]

cat file_di_istruzioni | psql [opzioni] [base_di_dati]

Il programma 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.

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.

Opzione Descrizione

-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 base_di_dati

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 nodo

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. 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 5 432 (corrispondente al valore predefinito), si può specificare con questa opzione il numero corretto da utilizzare.

-q

a sì che psql funzioni in modo «silenzioso», limitandosi all'emissione pura e semplice di quanto generato dalle 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 parola d'ordine 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.

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

Comando Descrizione

\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 base_di_dati \
  \[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.
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, cosa che permette di cambiare il nome dell'utente in questo comando.

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

Il programma psql può restituire i valori seguenti:

Segue la descrizione di alcuni esempi.

389.6.1   Variabile di ambiente «PAGER»

Il programma psql è sensibile alla presenza o meno della variabile di ambiente PAGER. Se questa esiste e non è vuota, psql utilizza 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, si fa in modo che l'output troppo lungo venga controllato da Less:

PAGER=less
export PAGER

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

389.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.(2)

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 con 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), accedendo al catalogo pg_database per 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.

389.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 viene 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.

389.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, tenendo conto poi che la documentazione di PostgreSQL fa spesso riferimento a queste, per cui 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 con un comando simile a quello seguente:

postgres:~$ psql -d template1[Invio]

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

template1=> SELECT * FROM pg_user;[Invio]

Figura 389.1. Esempio di un catalogo 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        |********|

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.

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 parole d'ordine 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 parole d'ordine indicate devono essere in chiaro o cifrate in qualche modo. L'esempio della figura 389.2 mostra gli stessi utenti a cui non viene abbinata alcuna parola d'ordine. La consultazione della tabella si ottiene con il comando SQL:

template1=> SELECT * FROM pg_shadow;[Invio]

Figura 389.2. Esempio di un catalogo 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        |      |

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

template1=> SELECT * FROM pg_database;[Invio]

Figura 389.3. Esempio di un catalogo 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

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 1 001, 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/, corrispondendo 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; in particolare, 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/, pertanto non si dovrebbero vedere percorsi assoluti in questa tabella. Viene mostrato in seguito quando può verificarsi questa condizione.

389.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; in tal caso dipende 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. L'esempio seguente archivia nel file base.tar.gz tutte le basi di dati che si articolano a partire da ~postgres/base/:

tar czvf base.tar.gz ~postgres/base[Invio]

L'esempio seguente, invece, archivia nel file pubblico.tar.gz solo la base di dati pubblico, che si trova esattamente nella directory ~postgres/base/pubblico/:

tar czvf pubblico.tar.gz ~postgres/base/pubblico[Invio]

Il recupero non è nulla di speciale, tranne per il fatto che si deve recuperare una basi di dati per intero, ovvero ciò che di solito si articola in una sottodirectory di ~postgres/base/. Se si 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 file system occorre ricordare che l'informazione sulla sua collocazione è contenuta nel catalogo pg_database, per cui è 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 dropdb, ricreandola 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, così si 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.

389.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[Invio]

mkdir /home/postgresql/base[Invio]

chown -R postgres: /home/postgresql[Invio]

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[Invio]

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

389.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, ma 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 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, si ottiene il file di testo mio_db.dump:

pg_dump mio_db > mio_db.dump[Invio]

Questo file va verificato, ricercando la presenza eventuale di segnalazioni di errore che vengono generate in presenza di dati che non possono essere riprodotti fedelmente; eventualmente, il file può anche 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[Invio]

Tabella 389.7. Alcune opzioni che possono essere usate con pg_dump.

Autenticazione Descrizione

-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 però 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 nodo

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 5 432 (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 parola d'ordine 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).

389.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:

[percorso]pg_dumpall [opzioni]

Il programma 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.

È molto probabile che pg_dumpall non si trovi nei percorsi previsti dalla variabile PATH. Infatti, questo programma, assieme a pg_dump, cambia a seconda della versione della struttura delle basi di dati di PostgreSQL. La collocazione normale potrebbe essere /usr/lib/postgresql/bin/, mentre le varie versioni specifiche potrebbero trovarsi in ~postgres/dumpall/*/.

postgres$ /usr/lib/postgresql/bin/pg_dumpall > basi_dati.dump[Invio]

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; 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[Invio]

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/data/pg_hda.conf per la configurazione dei sistemi di accesso e autenticazione, deve essere ripristinato manualmente.

389.9   Riferimenti

Appunti di informatica libera 2004.10.10 --- Copyright © 2000-2004 Daniele Giacomini -- <daniele (ad) swlibero·org>, <daniele·giacomini (ad) poste·it>


1) PostgreSQL   software libero con licenza speciale

2) 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.


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome postgresql_struttura_e_preparazione.html

[successivo] [precedente] [inizio] [fine] [indice generale] [violazione licenza] [translators] [docinfo] [indice analitico]

Valid ISO-HTML!