Formation DBA2
Dalibo SCOP
24.12
18 décembre 2024
Formation | Formation DBA2 |
Titre | PostgreSQL Avancé |
Révision | 24.12 |
ISBN | N/A |
https://dali.bo/dba2_pdf | |
EPUB | https://dali.bo/dba2_epub |
HTML | https://dali.bo/dba2_html |
Slides | https://dali.bo/dba2_slides |
Cette formation est sous licence CC-BY-NC-SA. Vous êtes libre de la redistribuer et/ou modifier aux conditions suivantes :
PostgreSQL® Postgres® et le logo Slonik sont des marques déposées par PostgreSQL Community Association of Canada.
Ce document ne couvre que les versions supportées de PostgreSQL au moment de sa rédaction, soit les versions 13 à 17.
PostgreSQL est :
# ps f -e --format=pid,command | grep -E "postgres|postmaster"
96122 /usr/pgsql-15/bin/postmaster -D /var/lib/pgsql/15/data/
96123 \_ postgres: logger
96125 \_ postgres: checkpointer
96126 \_ postgres: background writer
96127 \_ postgres: walwriter
96128 \_ postgres: autovacuum launcher
96131 \_ postgres: logical replication launcher
(sous Rocky Linux 8)
postmaster
background writer
checkpointer
walwriter
autovacuum launcher
stats collector
(avant v15)logical replication launcher
max_connections
(défaut : 100) - connexions réservées
Structure de la mémoire sous PostgreSQL
work_mem
)postgres$ ls $PGDATA
base pg_ident.conf pg_stat pg_xact
current_logfiles pg_logical pg_stat_tmp postgresql.auto.conf
global pg_multixact pg_subtrans postgresql.conf
log pg_notify pg_tblspc postmaster.opts
pg_commit_ts pg_replslot pg_twophase postmaster.pid
pg_dynshmem pg_serial PG_VERSION
pg_hba.conf pg_snapshots pg_wal
postgresql.conf
( + fichiers inclus)postgresql.auto.conf
pg_hba.conf
( + fichiers inclus (v16))pg_ident.conf
(idem)PG_VERSION
: fichier contenant la version majeure de
l’instancepostmaster.pid
external_pid_file
postmaster.opts
base/
: contient les fichiers de données
pgsql_tmp
: fichiers temporairesglobal/
: contient les objets globaux à toute
l’instancepg_wal/
: journaux de transactions
pg_xlog/
avant la v10archive_status
00000002 00000142 000000FF
pg_xact/
: état des transactions
pg_clog/
avant la v10pg_commit_ts/
, pg_multixact/
,
pg_serial/
pg_snapshots/
, pg_subtrans/
,
pg_twophase/
pg_logical/
pg_repslot/
pg_tblspc/
: tablespaces
Statistiques d’activité :
stats collector
(≤v14) & extensionspg_stat_tmp/
: temporairespg_stat/
: définitifpg_dynshmem/
pg_notify/
PostgreSQL est complexe, avec de nombreux composants
Une bonne compréhension de cette architecture est la clé d’une bonne administration.
Pour aller (beaucoup) plus loin :
N’hésitez pas, c’est le moment !
initdb
block_size
: 8 kowal_block_size
: 8 kosegment_size
: 1 Gowal_segment_size
: 16 Mo (option
--wal-segsize
d’initdb
en v11)postgresql.conf
( + fichiers inclus)postgresql.auto.conf
pg_hba.conf
( + fichiers inclus (v16))pg_ident.conf
(idem)Fichier principal de configuration :
/var/lib/…
)/etc/postgresql/<version>/<nom>/postgresql.conf
clé = valeur
include
,
include_if_exists
ALTER SYSTEM SET …
( renseigne
postgresql.auto.conf
)pg_ctl
ALTER DATABASE | ROLE … SET paramètre = …
SET
/ SET LOCAL
SHOW
pg_settings
pg_file_settings
pg_hba.conf
(Host Based Authentication)pg_ident.conf
: si mécanisme externe
d’authentificationhba_file
et ident_file
-- déclaration
CREATE TABLESPACE ssd LOCATION '/mnt/ssd/pg';
-- droit pour un utilisateur
GRANT CREATE ON TABLESPACE ssd TO un_utilisateur ;
-- pour toute une base
CREATE DATABASE nomdb TABLESPACE ssd;
ALTER DATABASE nomdb SET default_tablespace TO ssd ;
-- pour une table
CREATE TABLE une_table (…) TABLESPACE ssd ;
ALTER TABLE une_table SET TABLESPACE ssd ; -- verrou !
-- pour un index (pas automatique)
ALTER INDEX une_table_i_idx SET TABLESPACE ssd ;
CREATE TABLESPACE ssd LOCATION '/mnt/data_ssd/' ;
CREATE TABLESPACE ssd_tri1 LOCATION '/mnt/temp1' ;
CREATE TABLESPACE ssd_tri2 LOCATION '/mnt/temp2' ;
GRANT CREATE ON TABLESPACE ssd TO dupont ;
GRANT CREATE ON TABLESPACE ssd_tri1,ssd_tri2 TO dupont ;
default_tablespace
temp_tablespaces
:
L’accès à la base se fait par un protocole réseau clairement défini :
Les demandes de connexion sont gérées par le postmaster.
Paramètres : port
, listen_adresses
,
unix_socket_directories
, unix_socket_group
et
unix_socket_permissions
tcp_keepalives_idle
tcp_keepalives_interval
tcp_keepalives_count
client_connection_check_interval
(v14)ssl
, ssl_ciphers
,
ssl_renegotiation_limit
track_activities
,
track_activity_query_size
track_counts
, track_io_timing
et
track_functions
update_process_title
stats_temp_directory
(< v15)INSERT
, SELECT
…) par table
et indexpg_stat_user_*
pg_statio_user_*
pg_stat_activity
(requêtes)pg_stat_bgwriter
, pg_stat_checkpointer
(v17+)pg_locks
pg_stat_reset_shared()
pg_stats
default_statistics_target
)ANALYZE table
SQL est un langage déclaratif :
seq_page_cost
, random_page_cost
,
cpu_tuple_cost
, cpu_index_tuple_cost
,
cpu_operator_cost
parallel_setup_cost
,
parallel_tuple_cost
effective_cache_size
join_collapse_limit
from_collapse_limit
geqo
& geqo_threshold
(≥ 12
tables)plan_cache_mode
constraint_exclusion
enable_partition_pruning
cursor_tuple_fraction
synchronize_seqscans
N’hésitez pas, c’est le moment !
La mémoire & PostgreSQL :
shared_buffers
wal_buffers
max_connections
track_activity_query_size
max_connections
,
max_locks_per_transaction
work_mem
hash_mem_multiplier
maintenance_work_mem
autovacuum_work_mem
temp_buffers
Shared buffers ou blocs de mémoire partagée
effective_cache_size
( ~⅔ RAM)But : Le ring buffer permet de ne pas purger le cache à cause :
VACUUM
(écritures)COPY
, CREATE TABLE AS SELECT…
vacuum_buffer_usage_limit
2 extensions en « contrib » :
pg_buffercache
pg_prewarm
Pour synchroniser les blocs « dirty » :
COMMIT
Essentiellement :
pg_wal/
: journaux de transactions
archive_status
00000002 00000142 000000FF
pg_xact/
: état des transactionscheckpointer
checkpoint_timeout
max_wal_size
(pas un plafond !)CHECKPOINT
checkpoint_completion_target
× durée moy. entre 2
checkpointscheckpoint_warning
log_checkpoints
Nettoyage selon l’activité, en plus du
checkpointer
:
bgwriter_delay
bgwriter_lru_maxpages
bgwriter_lru_multiplier
bgwriter_flush_after
walwriter
wal_buffers
wal_writer_flush_after
fsync
= on
full_page_writes
= on
wal_compression
off
(défaut)pglz
(on
), lz4
,
zstd
(v15)synchronous_commit
commit_delay
/ commit_siblings
wal_level
, archive_mode
archive_command
ou archive_library
Mémoire et journalisation :
N’hésitez pas, c’est le moment !
PostgreSQL utilise un modèle appelé MVCC (Multi-Version Concurrency Control).
ROLLBACK
instantanéBEGIN ISOLATION LEVEL xxx
;READ COMMITTED
ctid
= (bloc, item dans le bloc)Table initiale :
xmin | xmax | Nom | Solde |
---|---|---|---|
100 | M. Durand | 1500 | |
100 | Mme Martin | 2200 |
xmin | xmax | Nom | Solde |
---|---|---|---|
100 | 150 | M. Durand | 1500 |
100 | Mme Martin | 2200 | |
150 | M. Durand | 1300 |
xmin | xmax | Nom | Solde |
---|---|---|---|
100 | 150 | M. Durand | 1500 |
100 | 150 | Mme Martin | 2200 |
150 | M. Durand | 1300 | |
150 | Mme Martin | 2400 |
xmin | xmax | Nom | Solde |
---|---|---|---|
100 | 150 | M. Durand | 1500 |
100 | 150 | Mme Martin | 2200 |
150 | M. Durand | 1300 | |
150 | Mme Martin | 2400 |
COMMIT
ou ROLLBACK
très rapideROLLBACK
instantanéVACUUM
xmin
/xmax
Après 4 milliards de transactions :
Concrètement ?
VACUUM FREEZE
HOT = Heap-Only Tuples
VACUUM
VACUUM
et VACUUM FREEZE
La gestion des verrous est liée à l’implémentation de MVCC
PostgreSQL possède un gestionnaire de verrous
pg_locks
xmax
pg_locks
:
max_locks_per_transaction
(+ paramètres pour la
sérialisation)lock_timeout
(éviter l’empilement des verrous)deadlock_timeout
(défaut 1 s)log_lock_waits
Divers seuils possibles, jamais globalement.
Paramètre | Cible du seuil |
---|---|
lock_timeout |
Attente de verrou |
statement_timeout |
Ordre en cours |
idle_session_timeout |
Session inactive |
idle_in_transaction_session_timeout |
Transaction en cours, inactive |
transaction_timeout
(v17) |
Transaction en cours |
TOAST : The Oversized-Attribute Storage Technique
Que faire si une ligne dépasse d’un bloc ?
PLAIN
/MAIN
/EXTERNAL
/EXTENDED
pg_toast_XXX
SELECT *
VACUUM
et le processus
d’arrière-plan autovacuum.N’hésitez pas, c’est le moment !
VACUUM
VACUUM
seul, ANALYZE
,
FULL
, FREEZE
VACUUM
: nettoie d’abord les lignes mortesvacuumdb
(shell, pour appels en masse)VACUUM
(SQL)autovacuum
(seuils)NB : L’espace est rarement rendu à l’OS !
Ne pas confondre :
VACUUM
seul
ANALYZE
VACUUM (ANALYZE)
VACUUM (FREEZE)
VACUUM FULL
PARALLEL
VACUUM (BUFFER_USAGE_LIMIT 2MB)
vacuum_buffer_usage_limit
SKIP_DATABASE_STATS
, ONLY_DATABASE_STATS
(v16+)SKIP_LOCKED
SET lock_timeout = '1s'
VERBOSE
Ponctuellement :
DISABLE_PAGE_SKIPPING
pg_stat_activity
ou top
pg_stat_user_tables
last_vacuum
/ last_autovacuum
last_analyze
/ last_autoanalyze
log_autovacuum_min_duration
Pour VACUUM
simple / VACUUM FREEZE
pg_stat_progress_vacuum
Partie ANALYZE
pg_stat_progress_analyze
Manuel ou via autovacuum
Pour VACUUM FULL
pg_stat_progress_cluster
VACUUM
VACUUM
, ANALYZE
,
FREEZE
FULL
autovacuum
(on !)autovacuum_naptime
(1 min)autovacuum_max_workers
(3)
Seuil de déclenchement =
threshold + scale factor × nb lignes de la table
VACUUM
autovacuum_vacuum_scale_factor
(20 %)autovacuum_vacuum_threshold
(50)autovacuum_vacuum_insert_threshold
(1000)autovacuum_vacuum_insert_scale_factor
(20 %)ANALYZE
autovacuum_analyze_scale_factor
(10 %)autovacuum_analyze_threshold
(50)VACUUM manuel | autovacuum |
---|---|
Urgent | Arrière-plan |
Pas de limite | Peu agressif |
Paramètres | Les mêmes + paramètres de surcharge |
maintenance_work_mem
autovacuum_work_mem
VACUUM
vacuum_cost_page_hit
/_miss
/_dirty
(1/ 10 ou 2 /20)vacuum_cost_limit
(200)vacuum_cost_delay
(en manuel : 0 ms !)autovacuum_vacuum_cost_limit
(identique)autovacuum_vacuum_cost_delay
(2 ms)Le but est de geler les numéros de transaction assez vite :
Quand le VACUUM
gèle-t-il les lignes ?
age ( pgclass.relfrozenxid )
vacuum_freeze_min_age
(50 Mtrx)
vacuum_freeze_table_age
(150 Mtrx)
autovacuum_freeze_max_age
(200 Mtrx)VACUUM FREEZE
préventif en période de maintenancepg_cancel_backend
+ VACUUM FREEZE
manuelVACUUM
check_pg_activity
: xmin
,
max_freeze_age
“Vacuuming is like exercising.
If it hurts, you’re not doing it enough!”(Robert Haas, PGConf.EU 2023, Prague, 13 décembre 2023)
last_(auto)analyze
/
last_(auto)vacuum
ALTER TABLE table_name SET (autovacuum_analyze_scale_factor = 0.01) ;
ALTER TABLE table_name SET (autovacuum_vacuum_threshold = 1000000) ;
vacuumdb
quotidienFREEZE
brutal après migration logique ou gros
import
VACUUM FULL
: dernière extrémitéVACUUM
fait de plus en plus de choses au fil des
versionsN’hésitez pas, c’est le moment !
Le partitionnement déclaratif apparaît avec PostgreSQL 10
Préférer un PostgreSQL récent
Ne plus utiliser l’ancien partitionnement par héritage.
VACUUM
(FULL
), réindexation, déplacements,
sauvegarde logique…pg_dump
parallélisableCREATE TABLE logs ( d timestamptz, contenu text) PARTITION BY RANGE (d) ;
CREATE TABLE logs_201901 PARTITION OF logs
FOR VALUES FROM ('2019-01-01') TO ('2019-02-01');
CREATE TABLE logs_201902 PARTITION OF logs
FOR VALUES FROM ('2019-02-01') TO ('2019-03-01');
…
CREATE TABLE logs_201912 PARTITION OF logs
FOR VALUES FROM ('2019-12-01') TO ('2020-01-01');
…
CREATE TABLE logs_autres PARTITION OF logs
DEFAULT ; -- pour ne rien perdre
DROP
ou DETACH
pg_dump
à chaudpg_basebackup
pg_receivewal
COMMIT
), intégrité,
durabilitépg_wal/
si échec d’archivage… et arrêt si
plein !(Non PITR)
2 étapes :
pg_receivewal
pg_basebackup
archiver
pg_receivewal
(flux de réplication)Préalables :
postgresql.conf
:
wal_level = replica
archive_mode = on
(ou always
)La commande d’archivage :
postgresql.conf
:
archive_command = '… une commande …'
archive_library = '… une bibliothèque …'
(v15+)archive_command
:archive_command='cp %p /mnt/nfs1/archivage/%f && sync /mnt/nfs1/'
archive_command='test ! -f /arch/%f && cp %p /arch/%f'
archive_command='/usr/bin/rsync -az %p postgres@10.9.8.7:/archives/%f'
archive_command='/opt/mon_script.sh %p %f'
archive_command='/usr/bin/pgbackrest --stanza=prod archive-push %p'
archive_command='/usr/bin/barman-wal-archive backup prod %p'
archive_command='/bin/true' # désactivation
postgresql.conf
(suite) :
archive_timeout = '… min'
wal_level
et/ou
archive_mode
pg_stat_archiver
pg_wal/archive_status/
.ready
et .done
pg_wal
pg_receivewal
s’arrêtepg_receivewal
tente de se
reconnecterpg_receivewal
SELECT pg_backup_start (
un_label
: textefast
: forcer un checkpoint ?)
rsync
et autres outilspostmaster.pid
, log
, pg_wal
,
pg_replslot
et quelques autresNe pas oublier !!
SELECT * FROM pg_backup_stop (
true
: attente de l’archivage)
Simple, mais à appliquer rigoureusement
pg_wal
restauré
Indiquer qu’on est en restauration
Commande de restauration
restore_command = '… une commande …'
postgresql.[auto.]conf
recovery_target_name
,
recovery_target_time
recovery_target_xid
,
recovery_target_lsn
recovery_target_inclusive
recovery_target_timeline
: latest
?recovery_target_action
: pause
pg_wal_replay_resume
pour ouvrir immédiatementstandby.signal
volontairement.history
recovery_target_timeline
latest
checkpoint_timeout
max_wal_size
wal_compression = on
pglz
(on
), lz4
,
zstd
gzip
,
bzip2
, lzma
…
barman
)list-server
, backup
,
list-backup
, recover
…pg_receivewal
pg_dump
N’hésitez pas, c’est le moment !
pg_wal
pg_resetwal
pg_surgery
Quelques pistes (liste non exhaustive)
fsync
est-il bien honoré de l’OS au disque ?
(batteries !)sar
, atop
…fsync
full_page_write
initdb --data-checksums
(création)pg_checksums --enable
(à posteriori)pg_checksums --check
kill -9
, rm -rf
,
rsync
, find … -exec
…pg_dump
pg_dumpall
COPY
psql
/ pg_restore
--section=pre-data
/ data
/
post-data
pg_checksums --check
pg_dump
, pg_dumpall
pg_basebackup
Pour les index :
amcheck
: vérification uniquement
pg_amcheck
(v14+)
REINDEX
REINDEX
pg_relation_filepath()
ctid
/
pageinspect
dd
pg_wal
pg_resetwal
permet de forcer le démarrageglobal/pg_control
pg_resetwal
… parfoispg_xact