Linux:Administration PostgreSQL
Sommaire[masquer] |
Initialisation
Le groupe de base de données ou l'espace de stockage des bases de données est initialisée par initdb. Le dossier doit appartenir à l'utilisateur de postgresql.
root# mkdir /var/lib/pgsql/data root# chown postgres /var/lib/pgsql/data root# su - postgres postgres$ initdb -d /var/lib/pgsql/data
Les bases postgres et template1 sont alors créées.
Il est possible de spécifier :
- --encoding=UTF8
- --locale=C
- --xlogdir=/chemin_vers_les_fichiers_wal
Par défaut, les droits sont initialisés à "trust" dans le fichier pg_hba.conf.
Définir le dossier par défaut :
PGDATA=/var/lib/pgsql/data export PGDATA
(dans ce cas, on peut faire initdb sans le -d)
Lancement manuel :
pg_ctl -D $PGDATA start
ou avec la valeur par défaut :
pg_ctl start
Rôles et droits d'accès
Sous postgres >=8.1, il n'y a pas de notion réelle d'utilisateur ou groupe, on parle de rôles.
CREATE ROLE nom_utilisateur; DROP ROLE nom_utilisateur;
Attention au droit de connexion : CREATE ROLE nom LOGIN; <=> CREATE USER nom;
Depuis le shell :
createuser nom_utilisateur dropuser nom_utilisateur
Voir les rôtes :
SELECT rolname FROM pg_roles; SELECT * FROM pg_roles;
ou
\du
Les attributs de rôles
- SUPERUSER (souvent donné à l'utilisateur postgres) : à tous les droits
- LOGIN : permettre la connexion
- CREATEDB : autoriser la création de base de données
- CREATEROLE : autoriser la création d'autres rôles
- PASSWORD : mot de passe pour le rôle (non lié au mot de passe système)
ALTER ROLE nom WITH PASSWORD 'pass'; ALTER ROLE nom CREATEROLE CREATEDB;
Désactiver un attribut :
ALTER ROLE test NOCREATEROLE;
Supprimer un rôle :
DROP ROLE nom;
Les droits
Par défaut, un objet est accessible à celui qui l'a créé, il est possible de donner des droits à d'autres rôles, par exemple :
GRANT SELECT ON nom_table TO nom_role;
Il est possible d'utiliser PUBLIC désignant tous les rôles et ALL pour tous les droits :
GRANT ALL ON nom_table TO PUBLIC;
Pour enlever un droit :
REVOKE UPDATE ON nom_table FROM nom_role;
Il est possible de créer des pseudo-groupes permettant de donner des droits à un rôle ou plusieurs rôles identiques :
CREATE ROLE nom_groupe;
Ajouter ou enlever des rôles de ce groupe :
GRANT nom_groupe TO nom_role1, ... ; REVOKE nom_groupe FROM nom_role1, ... ;
Ainsi si nom_groupe a des droits d'écriture sur un objet que role1 n'a pas, avec l'appartenance au groupe nom_groupe, cela sera le cas.
Attention, un rôle n'hérite pas directement des droits CREATEROLE, CREATEDB, LOGIN ou SUPERUSER. Il est possible d'utiliser la commande suivante pour changer de role :
SET ROLE nom_role
Opérations de bases
- Connexion à une base :
psql nom_base
Pour quitter :
nom_base=# \q
- Lister les bases :
nom_base=# \l
ou
nom_base=# SELECT datname FROM pg_database;
ou par la commande
psql -l
- Version de postgresql :
Une fois connecté à une base avec psql :
nom_base=# SELECT version();
- Lancer des commandes d'un fichier source :
nom_base=# \i fichier.sql
Création et suppression de bases de données
- Créer un base de données :
createdb nom_base
Créer une base du même nom que l'utilisateur courant :
createdb
Créer une base ayant pour propriétaire un autre rôle :
createdb -O nom_role nom_base
En utilisant la syntaxe SQL, une fois connecté :
nom_base=# CREATE DATABASE nom_base OWNER nom_role;
- Supprimer une base :
dropdb nom_base
Utilisation des templates :
CREATE DATABASE réalise une copie d'une base template, par défaut template1. Il est possible d'en spécifier une autre :
CREATE DATABASE nom_base TEMPLATE template0;
Il est possible ainsi de modifier template1 pour que la modification soit réalisée à toute nouvelle base. Il ne faut pas modifier template0 pour toujours avoir une base vierge.
Paramétrage/Options pour une base de données
Ajouter le langage plpgsql à une base :
createlang -U postgres -W plpgsql nom_base
Utilisation des tablespaces
Les tablespaces sont des espaces de stockages pour les données et indexes.
Vous pouvez lister les tablespaces existants :
SELECT spcname FROM pg_tablespace;
Il y a par défaut pg_default utilisé par les bases de données template1 et template0. Il est donc celui des bases de données créées avec ces templates.
Pour créer un tablespace :
CREATE TABLESPACE espace_bases LOCATION '/data/postgresql/data2';
A la création d'un tablespace, le dossier doit exister et avoir les droits pour l'utilisateur postgres :
postgres=# CREATE TABLESPACE espace_bases LOCATION '/tmp/datapostgres'; ERREUR: n'a pas pu configurer les droits du répertoire « /tmp/datapostgres » : Aucun fichier ou répertoire de ce type
postgres@beaufix:~/8.1/main/pg_tblspc$ mkdir /tmp/datapostgres postgres@beaufix:~/8.1/main/pg_tblspc$ ls -ld /tmp/datapostgres/ drwxr-xr-x 2 postgres postgres 4096 2009-12-28 22:24 /tmp/datapostgres/ postgres=# CREATE TABLESPACE espace_bases LOCATION '/tmp/datapostgres'; CREATE TABLESPACE postgres=# SELECT * FROM pg_tablespace; spcname | spcowner | spclocation | spcacl --------------+----------+-------------------+-------- pg_default | 10 | | pg_global | 10 | | espace_bases | 10 | /tmp/datapostgres | (3 lignes)
Autre façon de les lister :
\db SELECT * FROM pg_catalog.pg_tablespace;
Les tablespaces sont gérés par postgresql avec des liens symboliques dans le dossier pg_tblspc du dossier de data principal. Par exemple sous Debian Etch, il se situe dans /var/lib/postgresql/8.1/main/pg_tblspc :
postgres@beaufix:~/8.1/main/pg_tblspc$ ls -l total 0 lrwxrwxrwx 1 postgres postgres 17 2009-12-28 22:24 77632 -> /tmp/datapostgres
Pour spécifier un tablespace lors de la création d'un objet comme une table :
CREATE TABLE nom_table(i int) TABLESPACE espace_bases;
ou
SET default_tablespace = espace_bases; CREATE TABLE nom_table(i int);
Renommer un tablespace :
ALTER TABLESPACE tbs_index RENAME TO tbs_indexes;
Suppression :
DROP TABLESPACE IF EXISTS tbs_data;
Changement de tablespace:
alter table clients set tablespace tbs_data2;
Configuration de postgresql
Le fichier de configuration principal est postgresql.conf et se situe par défaut dans le dossier de stockage des bases de données. Il peut se situer dans un autre dossier s'il est précisé au démarrage avec par exemple :
/usr/lib/postgresql/8.3/bin/postgres -D /var/lib/postgresql/8.3/main -config_file=/etc/postgresql/8.3/main/postgresql.conf
Sauf exceptions, les paramètres peuvent être pris en compte grâce à la commande :
pg_ctl reload
Sous psql, il est possible de voir les paramètres courants :
show all; show autovacuum; #uniquement le paramètre autovacuum
Il existe aussi la table virtuelle pg_settings :
select * from pg_settings;
Il est possible de modifier un paramètre pour une session particulière de deux façons :
env PGOPTIONS='-c parametre=valeur' psql SET parametre TO valeur;
Paramètres de postgresql.conf
connexions
- listen_addresses
Sur quelles interfaces postgresql écoute (localhost par défaut si le paramètre est en commentaire) :
listen_addresses = 'localhost'
-> exemple pour une connexion distante autorisée :
listen_addresses = '*'
Il est aussi possible de passer l'argument -i au démarrage pour autoriser les connexions distantes (tcp).
- max_connections
Nombre maximum de connexions à 100 par défaut :
max_connections = 100
- superuser_reserved_connections
Il s'agit du nombre de connexions réservée pour les superutilisateurs sur le nombre totales de connexions autorisées (max_connections).
Paramètres mémoire et disques
Il faut d'abord vérifier au niveau système :
sysctl -a|grep kernel.shm
Paramètres des pg_hda.conf
Ce fichier détermine les autorisations d'accès des clients vers le serveur de base de données. Il se situe par défaut dans le dossier des données, par exemple /var/lib/postgresql/8.3/main/pg_hda.conf.
VACUUM et ANALYSE
VACUUM permet de libérer l'espace disque suite à des DELETE ou UPDATE.
VACUUM ne libère pas réellement l'espace disque mais marque l'espace comme réutilisable. Il faut lancer un VACUUM FULL pour libérer de l'espace mais cela n'est pas forcément efficace en terme de performance si les tables sont souvent modifiées.
ANALYSE lui maintient à jour les données de statistiques pour améliorer le plan d'exécution des requêtes.
VACUUM et ANALYSE sont exécutés automatiquement depuis la version 8.1 avec l'auto-vacuum.
Attention, track_counts doit être à On pour que l'auto-vacuum soit actif.
Pour les anciennes versions de postgresql, vous pouvez mettre une tâche de maintenance ainsi :
Créer le fichier /etc/cron.daily/postgresmaintenance
#!/bin/bash /usr/local/pgsql/bin/psql -U postgres -c "VACUUM;" > /dev/null /usr/local/pgsql/bin/psql -U postgres -c "ANALYSE;" > /dev/null
REINDEX
Administration
Arborescence des dossiers/fichiers
Considérons l'initialisation suivante : /usr/local/pgsql/bin/initdb -D /var/lib/postgres. Ainsi que CREATE DATABASE test;
L'OID de la base indique le répertoire sur le système de fichiers :
postgres=# SELECT oid,datname FROM pg_database;
oid | datname
-------+-----------
1 | template1
12015 | template0
12020 | postgres
16384 | test
ls -l /var/lib/postgres/base/ total 24 drwx------ 2 postgres users 12288 Oct 9 00:05 1 drwx------ 2 postgres users 4096 Oct 9 00:04 12015 drwx------ 2 postgres users 4096 Oct 9 00:05 12020 drwx------ 2 postgres users 4096 Oct 9 00:06 16384
Pour les tables, le fichier est identifié par son relfilenode :
test=# CREATE TABLE entier (i int); test=# SELECT relname,relfilenode FROM pg_class WHERE relname='entier'; relname | relfilenode ---------+------------- entier | 16385
Sur le FS :
ls -l /var/lib/postgres/base/16384/16385 -rw------- 1 postgres users 0 Oct 9 00:11 /var/lib/postgres/base/16384/16385
Ajoutons une donnée et vérifions qu'un bloc de 8k est créé :
test=# INSERT into entier VALUES (1); ls -l /var/lib/postgres/base/16384/16385 -rw------- 1 postgres users 8192 Oct 9 00:14 /var/lib/postgres/base/16384/16385
Gestion des processus
Voir les process en cours :
select * from pg_stat_activity;
Taille des bases et tables
Tables :
SELECT pg_relation_size('table');
Bases :
SELECT pg_database_size('base');
Pour un affichage converti :
SELECT pg_size_pretty(pg_database_size('base'));
Liste complète des bases :
SELECT pg_database.datname,pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database order by pg_database_size(pg_database.datname) desc; datname | size -----------+--------- test | 5990 kB postgres | 5982 kB template1 | 5889 kB template0 | 5881 kB
Sauvegardes et restauration de données
#!/bin/bash
save_dir=/var/backup/postgres
madate=`date +%Y%m%d`
mkdir -p $save_dir
chown postgres $save_dir
/usr/bin/find $save_dir -type f -mtime +7 -exec rm -f {} ';' > /dev/null
for bdd in $(su - postgres -c "psql -l -t" |awk '{print $1}'|grep -v template)
do
$(su - postgres -c "pg_dump -F c -f $save_dir/${bdd}-${madate}.dump ${bdd}")
done
divers
- verrouillage au niveau enregistrement
- pas de limitation du nombre de coeur
- pas possible de faire des hints comme oracle pour préciser le plan d'exécution
- test cpu :
create database myperf; \c myperf \timing SELECT sum(generate_series) FROM generate_series(1,1000000);
- test cpu+io disques/ram
CREATE TABLE test (id INTEGER PRIMARY KEY); INSERT INTO test VALUES (generate_series(1,1000000)); EXPLAIN ANALYSE SELECT COUNT(*) FROM test;
\h CREATE TABLE;
postgres=# \timing Chronométrage activé. postgres=# \timing Chronométrage désactivé.
postgres=# checkpoint; CHECKPOINT
postgres=# show shared_buffers; shared_buffers ---------------- 32MB (1 ligne)
select * from pg_settings where name like '%temp%';
select * from pg_settings where name like '%temp%'; select name,setting,unit,category,context from pg_settings where name='shared_buffers';
postgres=# select distinct context from pg_settings ; context ------------ backend user internal postmaster superuser sighup
SET default_tablespace = espace1; SELECT spcname FROM pg_tablespace;
Logs :
log_destination = 'stderr' logging_collector = on log_filename = 'postgresql-%Y%m%d.log' log_truncate_on_rotation = on log_rotation_age = 1d log_rotation_size = 0 log_connections = on log_disconnections = on log_checkpoints = on log_lock_waits = on log_temp_files = 1MB log_line_prefix = '%t - %u - %d - %r' log_statement='ddl' log_min_duration_statement = 1000
Cache disque :
hdparm -I /dev/sda|grep -i "write cache" * Write cache hdparm -W 0 /dev/sda /dev/sda: setting drive write-caching to 0 (off) write-caching = 0 (off) hdparm -I /dev/sda|grep -i "write cache" Write cache
myperf=# select count(*) from test; count --------- 1000000 (1 ligne) Temps : 120,269 ms myperf=# select count(*) from test;
myperf=# select pg_size_pretty(CAST(pg_relation_size('test')/120.269 * 1000 AS int8)) AS BYTES_PAR_SECOND;
bytes_par_second
------------------
255 MB
(1 ligne)
Test sans cache, stop postgres puis cache os :
sync echo 3 > /proc/sys/vm/drop_caches
relance postgres
On recommence \timing + select count(*) from test; on obtient par exemple 805,495 ms
Affichage étendu activé :
\x
Connaître le taux d'occupation du shared_buffer
SELECT count(*) * 100/4096 AS "% du cache utilise"
FROM pg_buffercache
WHERE relfilenode IS NOT NULL;
Visualisation des relations qui sont dans le buffer_cache
SELECT rel.relname AS "Relation", count(*) AS "Nb de tampons dans le cache" FROM pg_buffercache AS buf, pg_class AS rel WHERE buf.relfilenode=rel.relfilenode GROUP BY rel.relname ORDER BY count(*) DESC;
Résumé du contenu du cache, avec leur pourcentages (très utile)
Requête permettant de visualiser la quantité de données de chaque table présente en cache, mais
également le pourcentage que cette quantité représente par rapport à sa taille totale.
SELECT c.relname, pg_size_pretty(count(*)*8192) as BUFFERED,
round(100.0*count(*) / (SELECT setting FROM pg_settings
WHERE name='shared_buffers')::integer,1) as BUFFERS_POURCENT,
round(100.0*count(*)*8192 / pg_relation_size(c.oid),1) as POURCENT_DE_LA_RELATION
FROM pg_class c INNER JOIN pg_buffercache b
ON b.relfilenode = c.relfilenode
INNER JOIN pg_database d
ON (b.reldatabase = d.oid AND d.datname = current_database())
AND c.relname like '%'
GROUP BY c.oid, c.relname
ORDER BY 3 DESC
LIMIT 10;
Distribution du cache par utilisation
Requête permettant de comptabiliser les blocs de chaque relation par leur compteur
d'utilisation, de manière à voir précisément comment les scores d'utilisation
sont distribués pour chaque table
SELECT c.relname, count(*) as BUFFERS, usagecount
FROM pg_class c
INNER JOIN pg_buffercache b
ON b.relfilenode = c.relfilenode
INNER JOIN pg_database d
ON (b.reldatabase = d.oid AND d.datname = current_database())
AND c.relname like '%account%'
GROUP BY c.oid, c.relname, usagecount
ORDER BY 3 DESC
LIMIT 10;
checkpoint_segments : 10 mini et jusque 32 si le cache controleur dispose d'une batterie.
fsync = off synchronous_commit = off wal_sync_method = fsync_writethrough (windows) wal_sync_method = open_sync (linux)
wal_buffers = 16MB checkpoint_segments=32 checkpoint_completion_target = 0.9
archive_mode = on archive_command = '/tmp/local_backup_script.sh "%p" "%f"'
exemple /tmp/local_backup_script.sh
#!/bin/bash cp $1 /tmp/$2
forcer le changement de fichier wal:
select pg_switch_xlog();

