16. Administration du serveur
Ce chapitre s'adresse aux administrateurs qui exploitent miraj-server, le serveur réseau de MIRAJ. Il couvre le démarrage et l'arrêt, la configuration (ligne de commande et fichier XML), l'organisation du dossier de données, la durabilité, la sécurité opérationnelle, la supervision, la sauvegarde et les réglages de performance.
16.1 Démarrage et arrêt du serveur#
16.1.1 Commande de base#
miraj-server.exe --root D:\donnees --lang fr --log--root désigne le dossier de données du serveur (un dossier par base, plus un sous-dossier miraj pour les comptes et les journaux internes). En son absence, le serveur utilise un dossier data relatif au répertoire courant.
Pour le dépannage et la maintenance des comptes (voir 16.5.3), le serveur dispose d'un mode dédié :
miraj-server.exe --root D:\donnees --reset-accounts [--key-dir <dossier>]16.1.2 Arrêt du serveur#
Le seul arrêt ordonné de miraj-server est l'instruction SQL :
SHUTDOWN;Elle demande le privilège SHUTDOWN. Le serveur écrit toutes les tables modifiées, répond au client, écrit une dernière fois ce qui est arrivé entre-temps, puis le processus s'arrête (SHUTDOWN : serveur arrêté à la demande d'un client. dans la console ou le journal). Un arrêt par cette instruction ne laisse donc rien à rejouer au redémarrage.
Le serveur ne traite en revanche aucun signal d'arrêt : que l'arrêt vienne d'un Ctrl-C, de la fermeture du processus (arrêt d'un service, kill) ou d'une coupure de la machine, aucun point de sauvegarde final n'est écrit avant la sortie. Tout arrêt qui ne passe pas par SHUTDOWN doit donc être traité, du point de vue de l'administrateur, comme un arrêt brutal : c'est le journal d'écriture (WAL) et sa reprise au redémarrage qui garantissent l'intégrité des données (voir 16.4). C'est différent de l'usage embarqué de MIRAJ (bibliothèque miraj.dll) : là, la fermeture de l'instance écrit tout avant de rendre la main.
Un dossier de données n'est ouvert que par un processus à la fois : le fichier miraj.lck de la racine est verrouillé tant que le serveur tourne. miraj-cli, miraj-backup --root ou miraj-dump --root lancés sur ce dossier pendant ce temps échouent avec « Dossier de données … déjà ouvert par un autre processus MIRAJ » ; passer alors par le réseau.
16.1.3 Options de ligne de commande#
Toutes les options sont facultatives ; les valeurs par défaut sont celles appliquées quand ni le fichier miraj_config.xml ni la ligne de commande ne les changent (voir 16.2 pour l'ordre de priorité).
| Option | Valeur par défaut | Description |
|---|---|---|
--root <dossier> | data | Dossier de données du serveur. |
--config <fichier> | à côté de l'exécutable, sinon <root>\miraj_config.xml | Chemin explicite du fichier de configuration XML (voir 16.2). |
--port <port> | 7007 | Port TCP d'écoute. |
--bind <adresse> | 127.0.0.1 | Adresse d'écoute. Un avertissement est émis si une adresse non locale est choisie (voir 16.5.4). |
--lang <code> | en | Langue des messages d'erreur des sessions : en, fr, zh, hi, es, ar, pt, ru, de, ja. |
--log | désactivé | Tient à jour <root>\miraj\server.log (connexions, erreurs SQL, pannes internes ; voir 16.6). |
--result-buffer <Mo> | 64 | Mémoire gardée par connexion pour un client lent à lire son résultat. |
--write-timeout <secondes> | 60 | Attente maximale d'un client qui ne lit plus son résultat avant déconnexion. |
--connect-timeout <secondes> | 10 | Attente maximale de la poignée de main d'un client, TLS comprise : échéance absolue comptée dès l'acceptation, qu'un client envoyant un octet de temps en temps ne repousse pas. |
--max-connections <n> | 151 | Connexions simultanées au plus, de 1 à 100 000 (@@max_connections, modifiable par SET GLOBAL). Au-delà, le client reçoit l'erreur 1040 à la place de la poignée de main, sans qu'aucune session ne soit créée (voir 16.5.2). |
--max-connect-errors <n> | 100 | Échecs d'authentification consécutifs d'une même adresse qui la bloquent 15 minutes (@@max_connect_errors, modifiable par SET GLOBAL) ; voir 16.5.2. |
--proxy-protocol-from <adresse,…> | aucune | Adresses IP de miraj-proxy, séparées par des virgules. Une connexion venue de l'une d'elles doit commencer par l'en-tête PROXY v2, qui donne l'adresse du vrai client : c'est elle qui choisit le compte (user@hôte), subit le blocage après échecs et s'affiche dans SHOW PROCESSLIST. Un client ainsi annoncé n'est jamais localhost, même sur la boucle locale : les comptes @localhost (et ceux des hôtes 127.0.0.1, ::1) lui sont fermés. Sans en-tête dans le délai de connexion, la connexion est fermée. Voir 23.5. |
--initial-root-password <mot de passe> | tiré au sort | Mot de passe de root à la création du coffre des comptes (premier démarrage sur un dossier, ou --reset-accounts) ; ignoré, avec une note au démarrage, une fois le coffre créé (sauf pour donner un mot de passe à un root local qui n'en a pas) ; vide, refusé. Aussi par la variable d'environnement MIRAJ_INITIAL_ROOT_PASSWORD (priorité : ligne de commande, environnement, fichier de configuration). Voir 16.5.2. |
--require-password ON|OFF | ON | Refuse un compte sans mot de passe joignable depuis une autre machine (@@require_password, modifiable par SET GLOBAL ; voir 15.2). |
--local-infile ON|OFF | ON | Permet LOAD DATA LOCAL et LOAD XML LOCAL (fichier envoyé par le client) ; OFF : 1148 sans que le fichier ne soit demandé (@@local_infile, modifiable par SET GLOBAL ; voir 8.8). |
--idle-timeout <secondes> | 28800 (8 h) | Attente maximale d'une commande d'un client déjà connecté. |
--max-allowed-packet <octets> | 67108864 (64 Mio) | Taille maximale d'une commande d'un client, des données longues d'une requête préparée et du fichier d'un LOAD DATA LOCAL, de 1024 octets à 1 Gio (@@max_allowed_packet). Une commande plus longue reçoit l'erreur 1153 et la connexion est fermée ; des données longues ou un fichier plus longs reçoivent l'erreur 1153 et la connexion reste ouverte. Avant l'authentification, un message est limité à 64 Kio. |
--key-dir <dossier> | profil du compte qui lance le serveur | Dossier de la clé du coffre des comptes, hors du dossier de données (voir 16.5.1). |
--lock-wait-timeout <secondes> | 50 | Attente maximale d'un verrou de table explicite (LOCK TABLES), d'une ligne tenue par SELECT … FOR UPDATE, ou d'une table tenue par l'instruction longue d'une autre session (écriture dont le déclencheur ou la procédure dure, DDL), comptée depuis le début de l'instruction, avant l'erreur 1205 ; l'instruction refusée n'a rien écrit et la transaction reste ouverte (valeur initiale de lock_wait_timeout et innodb_lock_wait_timeout). |
--sql-mode <modes> | STRICT_TRANS_TABLES | Valeur initiale de la variable sql_mode des sessions (@@GLOBAL.sql_mode, modifiable par SET GLOBAL pour les sessions suivantes). Mode strict par défaut : une valeur NULL écrite dans une colonne NOT NULL, ou une valeur invalide, rend une erreur (1048, 1366…). --sql-mode "" (ou une liste sans STRICT_TRANS_TABLES, STRICT_ALL_TABLES ni TRADITIONAL) : mode non strict, la valeur devient la valeur implicite de la colonne (0, chaîne vide…) avec un avertissement ; c'est le réglage attendu par les applications écrites pour un serveur configuré en mode non strict. L'élément POSTGRESQL choisit le langage PostgreSQL de l'instance, pris en compte au démarrage seulement : le port principal parle alors le protocole PostgreSQL (voir 16.10) ; SET sql_mode ne peut ni l'ajouter ni le retirer (1231). |
--deferred-update ON|OFF | ON | Mise à jour différée : un UPDATE admissible d'une ligne désignée par sa clé ne la prend pas et est réévalué au COMMIT, si bien que deux transactions qui modifient la même ligne valident toutes les deux (voir 14.2). Valeur initiale de la variable deferred_update des sessions ; OFF : l'UPDATE prend sa ligne tout de suite. |
--concurrency mvocc|pessimistic | mvocc | Modèle de concurrence (voir 14.2). mvocc : contrôle multiversion optimiste, sans verrou de ligne ni attente. pessimistic rétablit l'ancien modèle à verrous de ligne (attente bornée, erreurs 1205 / 1213) ; option temporaire, le temps de comparer les deux modèles. |
--lazy-databases ON|OFF | ON | Chargement paresseux : les tables d'une base ne sont lues qu'à sa première utilisation (USE, table citée, SHOW TABLES FROM…), ce qui accélère le démarrage d'un dossier de nombreuses bases. La base système et les bases qui portent des événements planifiés sont ouvertes dès le démarrage ; un nœud de cluster ouvre toutes les siennes. OFF lit toutes les bases au démarrage. |
--lob-threshold <octets> | 8192 | Taille à partir de laquelle une valeur BLOB quitte la table et rejoint le magasin .bmrj. |
--lob-cache <Mo> | 128 | Taille du cache de lecture des BLOB déportés. |
--event-scheduler ON|OFF|DISABLED | OFF | État du planificateur d'événements au démarrage ; DISABLED interdit SET GLOBAL event_scheduler = ON ensuite. |
--parallel-threads <n> | un fil par cœur | Fils que toutes les requêtes du serveur peuvent occuper en tout (éditions Entreprise et Cluster ; sans effet en éditions Express et Developer ou sans licence valide, avec avertissement). |
--save-policy relaxed|statement|periodic | relaxed | Politique de durabilité (voir 16.4.1). |
--save-interval <millisecondes> | 5000 | Intervalle du vidage périodique de fond (politiques relaxed et periodic). |
--slow-query-log | désactivé | Active le journal des requêtes lentes. |
--slow-query-log-file <fichier> | <root>\miraj\slow.log | Fichier du journal des requêtes lentes ; le préciser active aussi le journal. |
--long-query-time <secondes> | 10 | Durée au-delà de laquelle une instruction est considérée comme une requête lente. |
--max-statement-time <secondes> | 300 (5 min) | Durée au-delà de laquelle une instruction est abandonnée (valeur initiale de la variable de session max_statement_time) ; 0 : sans limite. |
--max-statement-memory <octets> | 2147483648 (2 Gio) | Mémoire que les tris, regroupements, DISTINCT, fenêtres, opérations ensemblistes et jointures d'une instruction peuvent tenir ; au-delà, erreur 1038 (tri) ou 1114 (autres opérations), la session reste utilisable. 0 : sans limite. Valeur initiale de la variable max_statement_memory (session, SET GLOBAL, SET STATEMENT) ; voir 16.4.5. |
--max-server-memory <octets> | la moitié de la mémoire physique | Plafond de cette même mémoire pour toutes les instructions du serveur ensemble ; au-delà, erreur 9067. 0 : sans limite. Variable globale max_server_memory (SET GLOBAL) ; voir 16.4.5. |
--min-free-disk-space <octets> | 536870912 (512 Mio) | Espace libre minimal du volume des données : en dessous, les écritures qui ajoutent des données sont refusées (erreur 1021). 0 : désactivé. Variable globale min_free_disk_space (SET GLOBAL) ; voir 16.4.5. |
--group-concat-max-len <octets> | 1048576 (1 Mio) | Longueur maximale d'un résultat de GROUP_CONCAT et de JSON_ARRAYAGG, de 4 à 4 294 967 295 octets (valeur initiale de la variable group_concat_max_len). Un résultat plus long est tronqué, sans couper un caractère, avec l'avertissement 1260 : une requête ne peut pas faire allouer une chaîne géante. Chaque session la change par SET [SESSION] group_concat_max_len = n ; SET GLOBAL fixe celle des sessions ouvertes ensuite. |
--secure-file-priv <dossier> | vide (LOAD_FILE désactivé) | Seul dossier lisible par LOAD_FILE, pour les comptes ayant le privilège FILE. Ne doit ni contenir ni se trouver dans --backup-dir, le dossier de données, celui des clés, celui de la clé privée TLS (--tls-key) ou celui du journal des requêtes lentes, ni contenir le fichier de configuration ; sinon le serveur refuse de démarrer. |
--backup-dir <dossier> | vide (BACKUP / RESTORE refusés) | Seul dossier où BACKUP DATABASE écrit et d'où RESTORE DATABASE lit ; créé s'il n'existe pas. Mêmes règles que --secure-file-priv, dont il doit être disjoint : un compte FILE lirait sinon les sauvegardes par LOAD_FILE et en déposerait une forgée par INTO DUMPFILE (voir 16.7 et chapitre 19). |
--tls-cert <fichier.pem> / --tls-key <fichier.pem> | absent | Certificat et clé privée TLS. Dès qu'ils sont fournis, le serveur exige TLS : un client qui ne chiffre pas est refusé (erreur 3159). |
--allow-plain-with-tls | désactivé | Avec un certificat, accepte aussi les clients non chiffrés : TLS seulement proposé (ancien comportement). |
--require-tls | désactivé | Exige TLS en toutes circonstances, même avec --allow-plain-with-tls (suppose --tls-cert / --tls-key). |
--change-events-buffer-events <n> | 100000 | Événements de changement gardés en mémoire pour la reprise d'un abonné (chapitre 21 ; éditions Entreprise et Cluster, sans effet en Express). |
--change-events-buffer-size <octets> | 67108864 (64 Mio) | Taille maximale de ces événements. |
--change-events-bulk-rows <n> | 1000 | Lignes d'une table modifiées par une transaction au-delà desquelles un seul événement BULK est publié. |
--change-events-max-payload <octets> | 8000 | Taille maximale de la charge d'un NOTIFY. |
--change-events-max-listeners <n> | 64 | Abonnements LISTEN par session. |
--change-events-wait-timeout <secondes> | 30 | Attente de WAIT FOR CHANGES sans TIMEOUT (fraction permise). |
--change-events-retention <secondes> | 600 | Durée pendant laquelle une table reste suivie après la déconnexion de son dernier abonné ; 0 : arrêt immédiat. Sur un cluster, ces réglages sont propres à chaque nœud (voir 17.11). |
--cluster-config <cluster.toml> | cluster.toml à côté de l'exécutable | Édition Cluster : configuration du nœud dans une réplication multi-nœud (voir 16.1.4). |
--log-bin[=<chemin>], --server-id <n>, --gtid-domain-id <n>, --max-binlog-size <octets>, --binlog-expire-logs-seconds <n>, --expire-logs-days <n>, --sync-binlog <n>, --binlog-checksum CRC32|NONE, --gtid-strict-mode, --log-slave-updates | journal désactivé ; 1, 0, 1073741824, 0, 0, 0, CRC32, OFF, OFF | Journal binaire au format de la référence, pour des réplicas externes (éditions Entreprise et Cluster) : voir 17.13.1. Chaque option s'écrit aussi --nom=valeur. |
--data-encryption ON|OFF / --default-table-encryption ON|OFF / --encryption-passphrase-file <fichier> | OFF / ON / aucun | Chiffrement des données au repos (éditions Entreprise et Cluster) : voir chapitre 25. |
--license-file <miraj.lic> | variable MIRAJ_LICENSE, puis miraj\miraj.lic du dossier de données, puis à côté de l'exécutable | Fichier de licence (éditions Entreprise et Cluster) : voir chapitre 31. |
--mcp ON|OFF et --mcp-* | OFF | Point d'accès MCP pour les assistants IA (éditions Entreprise, Cluster et Developer) : voir chapitre 20. |
--rest ON|OFF | OFF | Point d'accès REST (HTTP/HTTPS, JSON), toutes éditions : voir chapitre 24. |
--rest-port <port> / --rest-bind <adresse> | 7009 / 127.0.0.1 | Port et adresse du point d'accès REST ; hors de la boucle locale, TLS obligatoire (--tls-cert, --tls-key). |
--rest-endpoints ON|OFF / --rest-tables ON|OFF / --rest-sql ON|OFF | ON / OFF / OFF | Familles d'accès REST ouvertes sur le serveur : endpoints écrits en SQL (CREATE ENDPOINT), lignes des tables, SQL libre. |
--rest-basic ON|OFF / --rest-basic-access <familles> | ON / ENDPOINTS | Connexion REST par compte et mot de passe (HTTPS ou boucle locale) et familles qu'elle permet. |
--rest-idle-timeout, --rest-statement-timeout, --rest-max-rows, --rest-cors-origins | 60, 30, 1000, vide | Délai d'une connexion HTTP sans requête, durée maximale d'une instruction, lignes par réponse, origines CORS admises. |
--journal-gap-replay | désactivé | Reprise forcée, le temps d'un démarrage : dans une base dont le journal est abîmé au milieu, les enregistrements intacts qui suivent la zone perdue sont aussi rejoués (voir 16.4.4). À n'utiliser qu'en dernier recours. |
--reset-accounts | — | Recrée le coffre des comptes avec le seul root local et un nouveau mot de passe (voir 16.5.3). Utilisable avec --root, --key-dir et --initial-root-password. |
--install-license <miraj.lic | MLIC1-… | -> | — | Installe une licence dans le dossier de données (--root) puis se termine, sans démarrer le serveur (voir 31.2). |
--machine-id | — | Affiche l'empreinte de la machine, pour une licence liée à une machine, puis se termine (voir 31.6). |
--help / -h / /? | — | Affiche l'usage et quitte. |
Le point d'accès MCP et le point d'accès REST ont chacun leurs options (--mcp-*, --rest-*) ; les tableaux détaillés sont aux chapitres 20 et 23. Les options de journal d'archive (sauvegarde incrémentielle continue) se règlent par miraj_config.xml et SET GLOBAL, pas par la ligne de commande (voir 19.1.5).
Remarque de terminologie : le nom des options en ligne de commande utilise des tirets (
--long-query-time), celui des clés XML et des variables de session des soulignés (long_query_time) ; ce chapitre respecte cette convention à chaque endroit.
16.1.4 Réplication (édition Cluster)#
L'édition Cluster ajoute la réplication multi-nœud : un nœud primaire écrit, des nœuds secondaires reçoivent son journal en continu et le rejouent en lecture seule. Les clients se connectent à un secondaire sur son port client habituel (7007 par défaut) ; toute tentative d'écriture y échoue en erreur
- Les nœuds communiquent entre eux sur un port distinct, en TLS mutuel (certificat signé par l'autorité du cluster). La configuration se fait par
--cluster-config:
[node]
id = "n1" # identifiant stable du nœud
listen = "0.0.0.0:7107" # port entre nœuds (pas celui des clients)
advertise = "10.0.0.1:7107" # adresse annoncée aux autres nœuds
[cluster]
name = "gestium-prod"
seeds = ["10.0.0.1:7107", "10.0.0.2:7107"]
tls_cert = "node.pem" # chemins relatifs au fichier
tls_key = "node-key.pem"
tls_ca = "cluster-ca.pem"
ack = "written" # ou "durable" : le secondaire vide son
# journal sur disque avant d'accuser
journal_retention_mb = 1024 # au-delà, un secondaire absent est
# réamorcé à son retourAu premier démarrage, tous les nœuds sont secondaires. Le rôle primaire se désigne une fois par :
SET GLOBAL cluster_role = 'primary';les autres nœuds rejoignent alors le primaire (copie des bases puis flux du journal). La promotion d'un secondaire utilise la même commande ; un ancien primaire relancé après une bascule est mis à l'écart (@@cluster_role = 'FENCED', lecture seule) jusqu'à ce qu'on le fasse rejoindre le nouveau primaire :
SET GLOBAL cluster_role = 'secondary';ses écritures non répliquées sont alors mises de côté dans <root>\miraj\quarantaine. Suivi de la réplication :
SHOW CLUSTER STATUS;
SELECT * FROM information_schema.MIRAJ_NODES;
SELECT * FROM information_schema.MIRAJ_REPLICATION;
SELECT @@read_only, @@cluster_role, @@cluster_epoch, @@cluster_primary;16.2 Fichier de configuration miraj_config.xml#
MIRAJ accepte une configuration par fichier XML, sur le modèle d'un fichier .cnf/.ini classique. Trois niveaux se combinent, dans cet ordre de priorité croissante :
- valeur par défaut interne ;
- valeur du fichier
miraj_config.xml; - argument de la ligne de commande (priorité la plus forte).
Le fichier lu est, dans l'ordre : le chemin donné par --config ; miraj_config.xml dans le dossier de miraj-server.exe, s'il y existe ; sinon <root>\miraj_config.xml (créé avec un squelette commenté s'il manque). Le chemin retenu est écrit au démarrage (Configuration : …). Une variable absente ou en commentaire garde sa valeur par défaut. Extrait :
<?xml version="1.0" encoding="UTF-8"?>
<miraj>
<!-- Langue des messages d'erreur des sessions (en, fr, zh, hi, es, ar, pt, ru, de, ja) -->
<!-- <language>en</language> -->
<!-- Politique de sauvegarde (relaxed, statement, periodic) -->
<!-- <save_policy>relaxed</save_policy> -->
<!-- Adresse d'écoute du serveur -->
<!-- <bind>127.0.0.1</bind> -->
<!-- Port TCP d'écoute du serveur -->
<!-- <port>7007</port> -->
<!-- Fichier <dossier>/miraj/server.log tenu à jour -->
<!-- <log>false</log> -->
</miraj>Pour appliquer une valeur, décommentez la ligne et changez la valeur ; le reste du fichier (les autres variables en commentaire) n'a pas besoin d'être modifié.
Un second fichier, miraj_default.xml, est régénéré à chaque démarrage du serveur : il liste toutes les variables reconnues avec leur valeur par défaut courante. C'est un fichier de référence, jamais relu par le serveur — ne pas y écrire ses propres réglages, ils seraient effacés au prochain démarrage. Utilisez-le pour retrouver, version après version, la liste complète des clés disponibles et leur valeur par défaut.
Les clés du fichier XML recouvrent les mêmes réglages que les options de ligne de commande : language, save_policy, save_interval, checkpoint_interval, checkpoint_large_table, lock_wait_timeout, sql_mode, deferred_update, concurrency, key_dir, data_encryption, default_table_encryption, encryption_passphrase_file (chapitre 25), lob_threshold, lob_cache, event_scheduler, parallel_threads, slow_query_log, slow_query_log_file, long_query_time, max_statement_time, group_concat_max_len, max_statement_memory, max_server_memory, min_free_disk_space, secure_file_priv, backup_dir, journal_archive, journal_archive_dir, journal_archive_max_lag (voir 19.1.5), require_password, local_infile, change_events_buffer_events, change_events_buffer_size, change_events_bulk_rows, change_events_max_payload, change_events_max_listeners, change_events_wait_timeout, change_events_retention, log_bin, server_id, gtid_domain_id, max_binlog_size, binlog_expire_logs_seconds, expire_logs_days, sync_binlog, binlog_checksum, gtid_strict_mode, log_slave_updates (voir 17.13.1), bind, port, log, result_buffer, write_timeout, connect_timeout, idle_timeout, max_allowed_packet, tls_cert, tls_key, require_tls, allow_plain_with_tls, max_connections, max_connect_errors, initial_root_password, cluster_config, license_file (chapitre 31), proxy_protocol_from, mcp, mcp_port, mcp_bind, mcp_idle_timeout, mcp_statement_timeout, mcp_max_rows, rest, rest_port, rest_bind, rest_idle_timeout, rest_statement_timeout, rest_max_rows, rest_cors_origins, rest_endpoints, rest_tables, rest_sql, rest_basic, rest_basic_access. Seuls --lazy-databases, --journal-gap-replay, --reset-accounts, --install-license, --machine-id et --config n'ont pas de clé XML (checkpoint_interval, checkpoint_large_table et journal_archive* n'ont pas d'option de ligne de commande). La liste exacte, avec la valeur par défaut de chacune, est celle de miraj_default.xml.
initial_root_password n'est lu qu'à la création du coffre des comptes : retirez-le du fichier une fois le serveur démarré, il y est en clair.
checkpoint_interval (300000 ms, soit 5 min, par défaut) n'a pas d'équivalent en ligne de commande : c'est l'intervalle entre deux points de sauvegarde (voir 16.4.2), réglable uniquement par ce fichier. Il en va de même pour checkpoint_large_table (64 Mo par défaut), la taille à partir de laquelle une table en mémoire n'est plus réécrite à chaque point de sauvegarde périodique (voir 16.4.2).
Usage recommandé : le fichier XML convient à un réglage permanent, propre à une instance (un dossier de données), qu'on ne veut pas répéter à chaque lancement dans un script ou un service Windows ; la ligne de commande reste utile pour un réglage ponctuel (diagnostic, script de test) qui doit l'emporter sur le fichier.
16.3 Organisation du dossier de données#
<dossier racine>/
miraj_config.xml configuration (si présente)
miraj_default.xml référence des valeurs par défaut, régénéré au démarrage
miraj.lck verrou du dossier : un seul processus à la fois
journal.reserve réserve d'espace (4 Mio) rendue au volume quand il est plein
miraj-bin.NNNNNN.mrb journal binaire, si --log-bin (index : miraj-bin.mrbi, voir 12.13)
replica-source.json configuration d'un réplica (CHANGE MASTER TO, voir 12.13.4)
<base>/
<table>.mrj une table = un fichier (format MIRA v2)
<table>.bmrj magasin des BLOB longs de la table (créé au premier dépôt)
<table>.dmrj une table disque (ENGINE = Aria / MyISAM / DISK) : lignes par pages
<table>.dbmrj grosses valeurs d'une table disque (créé au premier dépôt)
<table>.dmrj.ckpt point de sauvegarde en cours d'une table disque (temporaire)
doublewrite.mrw double écriture des pages des tables disque (réservée, pas encore écrite)
journal.mrl journal d'écriture (WAL) de la base
sequences.mrq séquences de la base (définition et état), si elle en a
views.mrv, routines.mrp, triggers.mrt, events.mre
vues, procédures et fonctions, déclencheurs, événements
replica.mrs état de réplication du nœud (édition Cluster)
miraj/
accounts.mra coffre chiffré des comptes
miraj.lic licence installée par --install-license (chapitre 31)
server.log journal serveur, si --log est actif
slow.log journal des requêtes lentes, si activé
quarantaine/ écritures non répliquées d'un nœud FENCED (édition Cluster)Points pratiques pour l'administration :
- Chaque base est un sous-dossier du dossier racine ; chaque table un fichier
.mrjdans ce sous-dossier. Créer ou supprimer une base revient à créer ou supprimer ce sous-dossier (fait par le serveur lui-même viaCREATE DATABASE/DROP DATABASE, jamais à la main pendant que le serveur tourne). - Un BLOB qui dépasse
--lob-threshold(8192 octets par défaut) est déposé dans le fichier.bmrjde sa table plutôt que dans le.mrj; ce fichier n'apparaît qu'après le premier dépôt d'un BLOB de cette taille. Les deux fichiers doivent être copiés ensemble : un.mrjsans son.bmrjassocié perd ses valeurs BLOB déportées. Après un abaissement de--lob-threshold, les valeurs déjà stockées qui atteignent le nouveau seuil rejoignent le.bmrjà l'ouverture de la base (la table est réécrite au point de sauvegarde suivant). Sur le primaire d'un cluster, ce déplacement passe par le journal, dans un plafond de 256 Mio par table (voir 17.7) : au-delà, les valeurs restent dans la table, lisibles, et une ligneAVERTISSEMENTest écrite dans le journal du serveur. - Une table disque est un fichier
.dmrjau lieu du.mrj(voir Moteurs de stockage) : ses lignes y restent, seuls ses index sont chargés en mémoire, avec un cache de pages de 256 Mo (non réglable pour l'instant). Ses valeurs de plus d'un quart de page vont dans<table>.dbmrj; comme pour le.bmrj, les deux fichiers vont ensemble. Les pages modifiées restent en mémoire jusqu'au point de sauvegarde, qui les écrit d'abord, avec le super-bloc et, après un DDL (COMMENT,CREATE/DROP INDEX…), les pages du nouveau schéma, dans<table>.dmrj.ckpt, synchronisé, puis à leur place : un.ckptcomplet trouvé à l'ouverture est rejoué (il répare une page déchirée par une coupure pendant l'écriture à sa place), un.ckptincomplet est ignoré (rien n'avait encore été écrit à sa place). Ne supprimez pas ce fichier à la main. Aucune page n'est écrite hors de ce chemin ; le fichierdoublewrite.mrw(un par base), relu à l'ouverture, ne sert pas encore : il est réservé à l'écriture anticipée de pages modifiées, à venir. Une page abîmée (support défaillant, fichier altéré) se signale parCHECK TABLEet se répare parREPAIR TABLE; le super-bloc et le schéma ont chacun une copie dans le fichier, qui prend le relais et les réécrit à l'ouverture (voir Maintenance des tables). journal.mrlest le journal d'écriture de la base : il permet de rejouer les écritures postérieures au dernier point de sauvegarde de chaque table en cas d'arrêt brutal (voir 16.4). Ne jamais le supprimer ou le modifier à la main.- Le coffre des comptes
miraj/accounts.mraest propre au dossier de données ; sa clé de déchiffrement est rangée ailleurs (voir 16.5.1). Copier un dossier de données sans sa clé rend le coffre illisible au redémarrage. - Sauvegarde : à l'arrêt du serveur (voir 16.1.2 et 16.7), une copie simple du dossier racine (bases,
miraj/, fichiers de configuration) suffit à en obtenir une image cohérente, à condition de copier aussi la clé du coffre des comptes si elle est nécessaire à la restauration (voir 16.5.1 et 16.7).
16.4 Durabilité et reprise après incident#
16.4.1 Politiques de sauvegarde (save_policy)#
MIRAJ écrit chaque instruction de modification dans le journal (WAL) de la base concernée avant de considérer l'instruction terminée ; la façon dont ce journal atteint le disque dépend de la politique choisie :
| Politique | Comportement | Perte maximale tolérée en cas d'arrêt brutal du processus | Perte maximale tolérée en cas de coupure de la machine |
|---|---|---|---|
relaxed (par défaut) | Le journal est écrit dans son fichier avant que l'instruction ne rende la main, sans attendre le disque ; un fil de fond le vide sur disque toutes les --save-interval ms (5000 par défaut). | Aucune (le fichier a déjà reçu l'écriture du système d'exploitation). | Les écritures du dernier intervalle --save-interval. |
statement | Comme relaxed, en attendant en plus le vidage sur disque à la fin de chaque instruction d'écriture. | Aucune. | Aucune. |
periodic | Rien n'est écrit avant le passage du fil de fond (toutes les --save-interval ms). | Les écritures des dernières --save-interval ms. | Les écritures des dernières --save-interval ms. |
Ces trois politiques peuvent aussi être choisies par session, sans changer le réglage du serveur :
SET SESSION save_policy = 'statement';(une quatrième valeur, manual, existe en interne mais est refusée en politique de serveur : elle n'écrirait jamais rien tant que la session ne l'ordonne pas, ce qui n'a pas de sens comme politique par défaut).
Comment choisir :
statementmaximise la sécurité (aucune perte possible, y compris lors d'une coupure de courant) au prix d'une latence d'écriture par instruction liée au disque — à retenir pour des données qu'aucune perte, même minime, ne peut affecter.relaxed(le réglage par défaut) offre un bon compromis : aucune perte en cas d'arrêt du seul processus serveur (le plus fréquent en pratique), et une fenêtre de perte bornée par--save-intervalseulement en cas de coupure de la machine elle-même.periodicréduit encore la latence d'écriture en échange d'une fenêtre de perte identique dans les deux cas (processus ou machine) — à réserver à des charges où le débit d'écriture prime sur la garantie de durabilité stricte.
Dans tous les cas, le journal lui-même reste cohérent : ce qui peut être perdu, ce sont les toutes dernières écritures non encore vidées, jamais l'intégrité du fichier.
16.4.2 Points de sauvegarde (checkpoints)#
Un point de sauvegarde consolide l'état courant des tables et permet de tronquer le journal d'écriture d'autant. Il se déclenche automatiquement :
- toutes les
checkpoint_intervalmillisecondes (300 000 ms, soit 5 min, par défaut — réglable uniquement viamiraj_config.xml, voir 16.2) ; - quand le journal dépasse 64 Mo ;
- à la fermeture propre d'une instance embarquée.
Une table en mémoire est écrite en entier dans son fichier .mrj. Pour ne pas réécrire toutes les 5 min une grosse table dont quelques lignes seulement ont changé, le point de sauvegarde périodique saute les tables en mémoire d'au moins checkpoint_large_table mégaoctets (64 par défaut) : leurs modifications restent dans le journal, qui les protège exactement comme avant. Elles sont écrites au point de sauvegarde complet (journal de 64 Mo atteint, SHUTDOWN, fermeture propre de l'instance), ou par une instruction qui a besoin de leur fichier à jour (RENAME TABLE, REPAIR TABLE…). Une sauvegarde à chaud (BACKUP) copie le journal avec elles.
| Petites tables | Tables d'au moins checkpoint_large_table Mo | |
|---|---|---|
| Point de sauvegarde périodique | écrites | reportées (le journal les protège) |
| Point de sauvegarde complet | écrites | écrites |
Le journal est alors raccourci jusqu'au plus ancien fichier qui en a encore besoin, et seulement si la rotation retire au moins autant qu'elle recopie. La sécurité en cas de coupure ne change pas, elle dépend de save_policy (voir 16.4.1). En contrepartie, la reprise après un arrêt brutal peut rejouer jusqu'à 64 Mo de journal au lieu d'une minute d'écritures. Les tables disque ne sont jamais reportées : leur point de sauvegarde n'écrit que les pages modifiées. checkpoint_large_table à 0 écrit toutes les tables à chaque point de sauvegarde, comme avant.
Un vidage du journal ou un point de sauvegarde qui échoue en arrière-plan (disque plein, fichier tenu par un antivirus, droits retirés) est retenté à chaque cycle et consigné dans le journal du serveur, une fois par base et par cause, sans répétition à chaque cycle : SAUVEGARDE : point de sauvegarde de la base … impossible : …, puis SAUVEGARDE : … rétabli quand il réussit de nouveau. Tant que l'échec dure, les modifications restent protégées par le journal, qui grossit.
Le vidage sur disque du journal lui-même (fsync) fait exception : s'il échoue (support défaillant, volume réseau perdu), le système a pu perdre des octets qu'il disait écrits, et un vidage suivant réussi ne le prouverait pas. Le journal de la base est alors arrêté : l'instruction qui attendait ce vidage (politique statement), puis toute écriture suivante sur cette base, rendent l'erreur 1026 (58030 en langage PostgreSQL), dont le message cite le fichier du journal et précise que le journal est arrêté et que l'issue des dernières validations est inconnue ; plus aucune écriture n'est acceptée sur cette base, les lectures continuent, et les points de sauvegarde n'y écrivent plus rien. Corriger la cause puis redémarrer le serveur : la base repart de ce que son journal porte réellement sur le disque. Les dernières validations, déjà visibles des autres sessions au moment de l'échec, sont à vérifier après le redémarrage.
Une instruction dont l'écriture dans le journal échoue (disque plein, par exemple) n'a, elle, aucun effet : rien n'en est visible ni gardé en attente, et elle peut être relancée une fois la cause levée.
16.4.3 Lignes supprimées et OPTIMIZE TABLE#
Un DELETE marque les lignes comme supprimées sans les retirer tout de suite. Elles sont retirées physiquement (compactage) :
- pendant les écritures, dès qu'elles atteignent 20 % des lignes de la table ;
- à chaque point de sauvegarde (voir 16.4.2), quel qu'en soit le nombre.
Le magasin de BLOB (.bmrj) n'est compacté automatiquement qu'au-delà de 64 Mo, quand au moins la moitié de son contenu est devenue orpheline.
OPTIMIZE TABLE t [, …] fait les deux tout de suite, sans condition de seuil : lignes supprimées retirées, fichier .mrj réécrit, magasin de BLOB compacté s'il contient des octets orphelins. On s'en sert après une grosse purge, ou pour choisir le moment de la réécriture (maintenance de nuit).
OPTIMIZE TABLE ventes, ventes_lignes;Le résultat compte une ou plusieurs lignes par table (Table, Op, Msg_type, Msg_text) :
info: nombre de lignes supprimées retirées, magasin de BLOB compacté ;- dernière ligne
status:OK,Table is already up to date(rien à retirer) ouOperation failed(table inconnue, vue, ou table tenue par une transaction ouverte ou unLOCK TABLES: le compactage est alors reporté au prochain point de sauvegarde où la table sera libre).
L'instruction valide la transaction ouverte de la session et prend le catalogue en écriture : les autres instructions attendent la fin de la réécriture. Il faut les privilèges SELECT et INSERT sur chaque table. Avec la politique manual, les lignes sont retirées en mémoire et le fichier n'est écrit qu'à la sauvegarde explicite. Dans l'édition Cluster, le compactage fait sur le primaire est journalisé et rejoué par les secondaires ; sur un secondaire, OPTIMIZE TABLE ne fait rien (note). Options acceptées sans effet : NO_WRITE_TO_BINLOG, LOCAL, WAIT n, NOWAIT.
16.4.4 Reprise après un arrêt brutal#
Au démarrage, le serveur ouvre les fichiers de table de chaque base puis rejoue les enregistrements du journal postérieurs au LSN (numéro de séquence du journal) déjà présent dans chaque fichier .mrj. Les écritures de fichiers sont atomiques (fichier temporaire, vidage, puis remplacement — sous Windows via MoveFileExW avec MOVEFILE_WRITE_THROUGH), et le magasin de BLOB (.bmrj) est toujours vidé sur disque avant le journal et le fichier de table qui le référencent : un arrêt brutal peut au pire laisser des octets de BLOB orphelins dans le .bmrj, jamais une référence sans contenu. Ce mécanisme est éprouvé par des arrêts brutaux du processus et par des coupures de courant (disque coupé en pleine écriture), pendant des écritures, des ALTER TABLE et des créations d'index, sur tables en mémoire comme sur tables disque : une écriture validée et vidée sur disque n'est jamais perdue, et un fichier abîmé est signalé plutôt que relu de travers.
Fichiers abîmés trouvés à l'ouverture : avant toute réparation, les fichiers concernés sont recopiés dans <root>\miraj\quarantaine\<horodatage>\<base>\ avec un rapport.txt, et chaque constat est consigné au démarrage (lignes RÉCUPÉRATION : … du journal du serveur).
- Fin du journal : une écriture interrompue (dernier enregistrement incomplet, suite de zéros) est retirée sans bruit, c'est l'effet normal d'un arrêt brutal. Une fin illisible plus longue qu'un enregistrement, sans rien de valide après (usure du support plutôt qu'écriture interrompue), est recopiée en quarantaine puis retirée, avec un constat.
- Zone abîmée au milieu du journal : seuls les enregistrements qui la précèdent sont rejoués ; ceux qui la suivent restent dans la copie en quarantaine.
--journal-gap-replayles rejoue aussi, le temps d'un démarrage : ils peuvent dépendre des modifications perdues, et une table dont un enregistrement ne s'applique pas garde ce qui l'a été avant lui (constatreprise forcée : …). Les tables ainsi complétées sont écrites aussitôt. - Fichiers
.mrjet.dmrjd'une même table (conversion de moteur interrompue) : le plus récent est gardé, un.mrjau contenu invalide perd ; l'autre est recopié en quarantaine avant d'être retiré. Si l'un des deux ne peut pas être lu (fichier tenu par un antivirus), rien n'est supprimé et la table reste illisible jusqu'au démarrage suivant. - Fichier de table abîmé (tronqué, vidé, fin illisible) : il n'est jamais relu comme une table plus petite ou sans écritures à rejouer ; la table est signalée illisible (constat au démarrage, erreur à son utilisation). La reprendre d'une sauvegarde ; pour une table disque,
REPAIR TABLE … EXTENDEDrécupère les lignes des pages lisibles. Des octets ajoutés après la fin valide d'un fichier de table sont ignorés, et le journal est rejoué normalement. - Base système
mirajillisible (journal tenu par un antivirus, disque en erreur) : son ouverture est retentée pendant quelques secondes, puis le serveur démarre sans elle. Elle est marquée indisponible (répertoire intact), les autres bases sont servies, et seules les connexions locales sont acceptées : un hôte distant reçoit l'erreur 9048, sur le port principal comme sur les points d'accès REST et MCP. Le journal du serveur l'annonce (BASE SYSTÈME INDISPONIBLE (…)) ; corriger la cause puis redémarrer le serveur.
Comme rappelé en 16.1.2, miraj-server ne dispose pas d'un arrêt propre : c'est précisément ce mécanisme de reprise, et non une séquence d'extinction, qui garantit l'intégrité des données à chaque redémarrage.
16.4.5 Garde-fous de mémoire et d'espace disque#
Trois réglages empêchent une instruction ou un disque plein de mettre le serveur en péril. Chacun refuse proprement l'instruction en cause : la session reste ouverte et utilisable, les données restent intactes.
| Variable | Portée | Défaut | Effet au-delà |
|---|---|---|---|
max_statement_memory | session et globale (SET, SET GLOBAL, SET STATEMENT) | 2 Gio | Erreur 1038 pour un tri, 1114 pour les autres opérations qui tiennent leurs lignes en mémoire (regroupement, DISTINCT, fenêtres, UNION / INTERSECT / EXCEPT, jointures par hachage, résultats intermédiaires) |
max_server_memory | globale (SET GLOBAL) | moitié de la mémoire physique | Erreur 9067 quand la mémoire tenue par toutes les instructions en cours dépasserait le plafond ; réessayer plus tard |
min_free_disk_space | globale (SET GLOBAL) | 512 Mio | Erreur 1021 pour INSERT, UPDATE et les autres écritures qui ajoutent des données quand l'espace libre du volume passe sous le seuil |
0 lève chacune de ces limites. Les lectures, ROLLBACK, DELETE, TRUNCATE, DROP et KILL restent permis sous le seuil d'espace libre : ce sont eux qui rendent de la place. Le fichier journal.reserve du dossier de données (4 Mio) est rendu au volume quand celui-ci est plein, pour qu'un vidage ou une suppression puisse encore s'écrire dans le journal. Un disque réellement plein donne aussi l'erreur 1021 (ou 1114 pour la table écrite), plutôt qu'une erreur interne.
SET max_statement_memory = 1048576; -- 1 Mio pour la session
SELECT v FROM t ORDER BY v DESC LIMIT 15000, 1;
SELECT v, COUNT(*) FROM t GROUP BY v LIMIT 1;ERREUR 1038 (HY001) : Out of sort memory: the statement exceeds max_statement_memory (1 Mio)
ERREUR 1114 (HY000) : The table '#sql_tmp (1 Mio)' is fullSET GLOBAL max_server_memory = 100000;
SELECT DISTINCT v FROM t LIMIT 1;ERREUR 9067 (HY001) : Out of server memory: the statements running on the server would exceed max_server_memory (100000 octets); retry laterSET GLOBAL min_free_disk_space = 900000000000000;
INSERT INTO gestion.clients VALUES (50, 'Bloqué', NULL);ERREUR 1021 (HY000) : Disk full (15829 MiB free on the volume of 'D:\donnees\gestion', below min_free_disk_space (858306884 MiB)); the write was refused, free some space and retrySET GLOBAL … = DEFAULT rend la valeur de départ. La mémoire tenue en ce moment par les instructions du serveur se lit dans SHOW GLOBAL STATUS LIKE 'Miraj_server_memory_used'.
Ces limites ne débordent pas sur disque : un tri ou un regroupement trop gros est refusé, pas écrit dans un fichier temporaire. Le résultat renvoyé au client, les tables, les index et les caches ne sont pas comptés.
Le texte d'une requête est borné de même : un même envoi (une instruction, ou un script de plusieurs instructions envoyé d'un bloc) compte au plus 2 millions d'éléments de syntaxe (une valeur d'un INSERT … VALUES ou d'une liste IN en vaut un, une colonne, une table ou un SELECT quelques-uns) et 8 millions de jetons (mots, nombres, signes). Au-delà, il est refusé par l'erreur 7620 (SQLSTATE 54001, aussi en langage PostgreSQL) avant toute exécution :
ERREUR 7620 (54001) : Statement too complex: more than 2000000 syntax elements in one script (split it into several statements)Un INSERT … VALUES de plus de deux millions de valeurs (de l'ordre de 25 Mo de lignes ordinaires) se découpe donc en plusieurs instructions. miraj-dump restore et miraj-cli connecté à un serveur envoient un fichier instruction par instruction : seule une instruction trop grosse est refusée. miraj-cli ouvert sur un dossier de données exécute en revanche un fichier .sql d'un seul bloc (chapitre 26) : un très gros script s'y charge plutôt par la console connectée à un serveur.
16.5 Sécurité opérationnelle#
16.5.1 Coffre des comptes et gestion de la clé#
Les comptes (utilisateurs, mots de passe, privilèges, rôles) sont gardés dans un coffre chiffré et authentifié par AES-256-GCM, <root>\miraj\accounts.mra — jamais journalisé, écrit de façon atomique, protégé contre la restauration d'une copie ancienne par un numéro de génération croissant.
La clé de 32 octets qui protège ce coffre est rangée hors du dossier de données :
- sous Windows, elle est chiffrée par DPAPI pour la machine (lisible par n'importe quel compte de cette machine, y compris SYSTEM au démarrage sans session ouverte), dans
%LOCALAPPDATA%\MIRAJ\keys; - sur les autres systèmes, dans un fichier aux droits
0600; --key-dir <dossier>(ou la clé XMLkey_dir) permet de choisir un autre emplacement, par exemple pour partager la clé entre plusieurs services ou la ranger sur un support distinct du dossier de données.
Conséquence pour la sauvegarde et le déploiement : copier uniquement le dossier de données ne suffit pas à pouvoir rouvrir les comptes sur une autre machine ou sous un autre compte Windows ; il faut aussi transférer la clé (ou son dossier --key-dir), en la protégeant au moins aussi bien qu'un mot de passe administrateur.
16.5.2 Mot de passe initial, connexions et écoute réseau#
Mot de passe initial de root. Au premier démarrage de miraj-server sur un dossier, le coffre des comptes est créé avec le seul compte root local, qui reçoit un mot de passe de 24 caractères tiré au sort par le générateur du système. Il est affiché une seule fois sur la console, avec la commande pour le changer, et n'est écrit nulle part (ni dans server.log, ni dans le coffre autrement que sous forme de vérificateur) :
================================================================================
Compte root@localhost créé avec le mot de passe provisoire : Xq7mPt3hKc9WbZ2rNf8sLd4v
Il n'est affiché qu'une fois et n'est écrit nulle part : notez-le, puis changez-le :
ALTER USER root@localhost IDENTIFIED BY 'nouveau mot de passe';
================================================================================Avec un mot de passe fixé à l'avance, la console n'affiche que sa provenance :
Compte root@localhost créé avec le mot de passe initial donné par --initial-root-password (à retirer ensuite).Pour une installation automatisée, fixez-le vous-même par --initial-root-password, par la variable d'environnement MIRAJ_INITIAL_ROOT_PASSWORD (préférable : la ligne de commande d'un processus est visible des autres utilisateurs) ou par la clé initial_root_password du fichier de configuration ; il n'est alors pas affiché. Une valeur vide passée par la ligne de commande ou par la variable est refusée (le serveur ne démarre pas). À la création du coffre, server.log consigne d'où vient le mot de passe (ligne de commande, variable, fichier de configuration ou tirage), jamais le mot de passe lui-même. Ces réglages sont ignorés, avec une note, dès que le coffre existe, sauf si le root local y est resté sans mot de passe (coffre écrit par le moteur embarqué, miraj-cli par exemple, avant le premier démarrage du serveur) : il reçoit alors le mot de passe initial. Un root local sans mot de passe est signalé par un avertissement à chaque démarrage. Dans un cluster, seul le primaire crée les comptes : un secondaire qui démarre sur un dossier vierge sans mot de passe initial crée un coffre d'attente dont le root est inaccessible, puis reçoit les comptes du primaire. Remplacez le mot de passe provisoire dès la première connexion :
ALTER USER 'root'@'localhost' IDENTIFIED BY 'un mot de passe robuste';Écoute réseau. Le serveur écoute par défaut sur la boucle locale (127.0.0.1). Choisir une adresse d'écoute non locale (--bind) sans TLS déclenche un avertissement, et le serveur signale les comptes sans mot de passe qui deviendraient alors joignables à distance. Tant que require_password est actif (défaut), un tel compte ne peut d'ailleurs pas être créé (erreur 9033, voir 15.2).
Nombre de connexions. Au plus --max-connections connexions (151 par défaut) sont servies à la fois ; chacune prend sa place avant que sa session ne soit créée. Au-delà, le client reçoit l'erreur 1040 (« Too many connections ») à la place de la poignée de main, et le refus est signalé au plus une fois par minute dans le journal. Une poignée de main doit s'achever en --connect-timeout secondes, TLS comprise, comptées dès l'acceptation.
Échecs d'authentification. Chaque réponse fausse (erreur 1045) est comptée pour l'adresse du client : la réponse est retardée de 100 ms au premier échec, du double à chaque échec suivant, 5 s au plus. Au bout de --max-connect-errors échecs consécutifs (100 par défaut), l'adresse est bloquée 15 minutes, délai relancé par chaque nouvelle tentative : ses connexions sont refusées dès l'acceptation par l'erreur 1129, même avec le bon mot de passe. Une authentification réussie remet le compte de l'adresse à zéro. Blocages et refus répétés sont inscrits dans le journal (SÉCURITÉ : …). Pour débloquer toutes les adresses :
FLUSH HOSTS; -- privilège RELOADLes adresses sans échec depuis une heure sont oubliées, et au plus 10 000 adresses sont suivies (la plus anciennement active est évincée au-delà). Attention : tous les clients d'une même machine partagent son adresse, y compris la boucle locale ; un script qui se trompe de mot de passe en boucle peut bloquer les autres clients de sa machine.
Identité avant authentification. Tant qu'une connexion n'a pas achevé son authentification, elle n'appartient à aucun compte : SHOW PROCESSLIST la montre en unauthenticated user, aux seuls comptes qui voient toutes les sessions (PROCESS), seuls à pouvoir l'arrêter par KILL.
16.5.3 --reset-accounts : procédure de secours#
Un coffre des comptes altéré, supprimé ou dont la clé est absente/illisible empêche le démarrage du serveur. Un coffre supprimé alors que sa clé existe encore est refusé (message « accounts.mra a disparu alors qu'une clé existe pour ce dossier ») dès que le dossier contient des données : une base, ou dans miraj/ un fichier autre qu'un journal (*.log). Supprimer le coffre ne rend donc pas l'accès à root sans mot de passe. Seul cas accepté : un dossier de données supprimé entièrement puis recréé au même chemin, sans aucune base. La clé de l'ancien dossier, restée dans le dossier des clés, est alors ignorée (détachée de ce chemin, pas effacée : un ancien dossier déplacé ailleurs la retrouve), une note « dossier de données neuf » est écrite au démarrage et un coffre neuf est créé comme au premier démarrage.
La procédure de secours locale est :
miraj-server.exe --root D:\donnees --reset-accounts [--key-dir <dossier>]Cette commande recrée le coffre avec pour seul compte le root local, puis se termine (elle ne démarre pas le serveur réseau). root reçoit un nouveau mot de passe tiré au sort, affiché une seule fois sur la console comme au premier démarrage, ou celui de --initial-root-password (ou de MIRAJ_INITIAL_ROOT_PASSWORD), qui n'est pas affiché. Elle doit être exécutée localement, avec un accès au dossier de données et, implicitement, un accès équivalent à celui de la clé. Après un --reset-accounts :
- tous les comptes et privilèges précédemment définis sont perdus (seul
rootlocal subsiste) ; recréez les comptes applicatifs et redonnez les privilèges nécessaires ; - remplacez sans attendre le mot de passe provisoire de
root(voir la commandeALTER USERci-dessus).
N'utilisez cette procédure qu'en dernier recours (coffre corrompu, clé perdue, compte administrateur bloqué sans autre accès) : elle ne restaure rien, elle repart d'un état vierge de comptes.
16.5.4 Recommandations pour un déploiement en production#
- En édition Entreprise ou Cluster, chiffrez les données au repos dès l'installation (
--data-encryption ON, chapitre 25) et gardez la phrase secrète hors de la machine.
- Conservez l'écoute sur la boucle locale (
127.0.0.1, valeur par défaut) tant qu'un pare-feu ou un tunnel applicatif ne protège pas un accès plus large ; ne choisissez une adresse non locale qu'après avoir sécurisé tous les comptes par mot de passe. - Activez TLS (
--tls-cert/--tls-key) dès que les clients se connectent au travers d'un réseau qui n'est pas physiquement isolé : il est alors exigé de tous les clients. N'utilisez--allow-plain-with-tlsque le temps de migrer des clients qui ne savent pas encore chiffrer. - Ajustez
--max-connectionsau nombre de clients attendus et laissez--max-connect-errorsà une valeur basse : un essai de mots de passe est ralenti puis bloqué. - Séparez la clé du coffre des comptes (
--key-dir) du support de sauvegarde du dossier de données, ou documentez clairement qu'elle doit être copiée à part lors d'une restauration. - Laissez
secure_file_privvide (valeur par défaut,LOAD_FILEdésactivé) sauf besoin explicite ; si vous l'activez, pointez-le vers un dossier dédié, distinct du dossier de données, du dossier des clés, de celui de la clé TLS et du dossier des sauvegardes (le serveur refuse de démarrer sinon). - Démarrez systématiquement avec
--log(voir 16.6) pour conserver une trace des erreurs SQL et des incidents internes. - Gardez à l'esprit l'absence d'arrêt propre (16.1.2) : prévoyez la politique de sauvegarde (16.4.1) en fonction de la perte de données que vous pouvez tolérer en cas de coupure, plutôt que de compter sur une extinction soignée du service.
16.6 Supervision#
16.6.1 SHOW STATUS et SHOW VARIABLES#
SHOW VARIABLES; -- réglages courants de la session/du serveur
SHOW VARIABLES LIKE 'save_%';
SHOW STATUS; -- compteurs d'activité (portée de la session)
SHOW GLOBAL STATUS; -- mêmes compteurs, pour tout le serveur
SHOW STATUS LIKE 'Miraj_%';SHOW VARIABLES restitue les mêmes valeurs que SELECT @@nom pour chaque variable ; c'est ce que lisent à la connexion les outils clients courants (consoles graphiques, connecteurs).
SHOW STATUS (ou SHOW SESSION STATUS, information_schema.SESSION_STATUS) rend les compteurs Questions, Com_*, Bytes_*, Handler_*, Select_*, Sort_*, Created_tmp_* et Innodb_rows_* de la session seule ; SHOW GLOBAL STATUS (information_schema.GLOBAL_STATUS) ceux de toutes les sessions depuis le démarrage. Les autres compteurs n'existent que pour le serveur et ont la même valeur dans les deux portées. Une instruction est comptée dès son début : le SHOW STATUS qui lit les compteurs se compte lui-même.
SHOW STATUS expose notamment, à ce jour :
| Variable | Signification |
|---|---|
Miraj_parallel_fair_share | Fils qu'une requête peut prendre en ce moment : le budget divisé par le nombre d'instructions en cours (voir 16.8). |
Miraj_parallel_queries | Nombre de requêtes ayant utilisé l'exécution parallèle (éditions Entreprise et Cluster). |
Miraj_parallel_queries_downgraded | Requêtes parallèles dont le nombre de fils a été réduit à leur part équitable. |
Miraj_parallel_queries_serialized | Requêtes retombées en exécution série faute de fils disponibles. |
Miraj_parallel_queries_serialized_load | Requêtes parallélisables exécutées en série parce que le serveur avait autant d'instructions en cours que de fils. |
Miraj_parallel_queries_serialized_volume | Agrégations poursuivies en série après leur premier morceau (presque un groupe par ligne). |
Miraj_parallel_statements_active | Instructions en cours d'exécution (hors attentes : SLEEP, WAIT FOR CHANGES, verrous de table). |
Miraj_parallel_workers | Fils du budget de parallélisme configuré. |
Miraj_parallel_workers_busy | Fils actuellement occupés. |
Questions | Instructions exécutées (de la session, ou depuis le démarrage pour toutes les sessions en portée globale), réussies ou non, hors erreurs de syntaxe (une par instruction d'un lot ; celles des procédures et des déclencheurs ne comptent pas). |
Com_select, Com_insert, Com_update, Com_delete, Com_set_option, Com_show_status… | Les mêmes instructions par genre, sous les noms usuels des outils de supervision (Com_insert_select, Com_update_multi, Com_begin, Com_commit, Com_create_table, Com_xa_start…). Les instructions propres à MIRAJ (jetons, LISTEN, REFRESH VIEW…) ne sont comptées que dans Questions. |
Bytes_received, Bytes_sent | Octets reçus du client et envoyés vers lui par la connexion réseau (0 pour une session embarquée), ou par toutes les connexions depuis le démarrage en portée globale. |
Handler_read_key, Handler_read_next, Handler_read_rnd_next | Lectures de table : recherches par index (une par lecture qui passe par un index), lignes lues à la suite d'une recherche par index secondaire, lignes lues par un parcours de table. |
Handler_write, Handler_update, Handler_delete | Lignes écrites par les INSERT / REPLACE / LOAD, modifiées par les UPDATE et supprimées par les DELETE, celles des procédures, des fonctions et des déclencheurs comprises. |
Handler_commit, Handler_rollback | Transactions validées (celles d'une seule instruction comprises) et annulées. |
Handler_savepoint, Handler_savepoint_rollback | Points de sauvegarde posés dans une transaction ouverte (SAVEPOINT), annulations jusqu'à l'un d'eux (ROLLBACK TO SAVEPOINT). |
Select_scan, Select_range, Select_full_join | Lectures de table complètes, lectures bornées par un index, jointures dont la table jointe est lue en entier, sans index (une table jointe lue par un index ne compte pas). |
Sort_rows, Sort_scan, Sort_range, Sort_priority_queue_sorts | Lignes triées ; tris d'une instruction qui lit une table en entier, tris d'une instruction dont les lectures passent par un index ; tris bornés par un LIMIT. |
Created_tmp_tables | Résultats intermédiaires rangés en mémoire (regroupement, DISTINCT). |
Innodb_rows_read, Innodb_rows_inserted, Innodb_rows_updated, Innodb_rows_deleted, Innodb_page_size | Les mêmes lignes lues et écrites, et la taille de page des tables disque, sous les noms que lisent les outils de supervision. |
Open_tables, Opened_tables, Open_table_definitions, Opened_table_definitions | Tables des bases ouvertes ; tables ouvertes ou créées depuis le démarrage. |
Created_tmp_disk_tables, Created_tmp_files, Sort_merge_passes, Select_full_range_join, Select_range_check, Handler_read_first, Handler_read_last, Handler_read_prev, Handler_read_rnd | Présents pour les outils, toujours à 0 : le moteur trie et regroupe en mémoire, ne parcourt jamais un index dans son ordre et ne relit pas une ligne triée par sa position. |
Connections | Tentatives de connexion depuis le démarrage, refusées comprises. |
Threads_running | Sessions en train d'exécuter une instruction (celle qui lit comprise). |
Slow_queries | Nombre de requêtes consignées dans le journal des requêtes lentes. |
Uptime | Secondes écoulées depuis le démarrage du serveur. |
Max_statement_time_exceeded | Nombre d'instructions abandonnées pour dépassement de max_statement_time. |
Threads_connected | Connexions ouvertes (1 pour une session embarquée). |
Max_used_connections | Plus grand nombre de connexions simultanées depuis le démarrage. |
Connection_errors_max_connections | Connexions refusées faute de place (max_connections, erreur 1040). |
Aborted_connects | Connexions fermées avant l'authentification : échec d'authentification, poignée de main illisible ou trop lente, adresse bloquée. |
Miraj_server_memory_used | Mémoire (octets) tenue en ce moment par les tris, regroupements et jointures de toutes les instructions en cours, comptée contre max_server_memory (voir 16.4.5). |
Miraj_checkpoint_tables_held | Tables dont le dernier point de sauvegarde a été empêché (transaction aux écritures non validées, LOCK TABLES, copie en cours) et qu'aucun n'a écrites depuis : le journal de leur base garde leurs enregistrements et grandit. Le serveur le signale aussi dans son journal au-delà de 60 s. |
Miraj_disk_pages_spilled, Miraj_disk_spill_bytes | Tables disque : pages modifiées rangées au fichier de débordement (<uuid>.dswap, au-delà de 64 Mo de pages sales par table) depuis le démarrage, et octets de pages qui s'y trouvent en ce moment. Une valeur durablement élevée de Miraj_disk_spill_bytes signale une longue transaction ou un très gros chargement. |
Miraj_journal_archive, Miraj_journal_archive_databases, _bases, _bases_pending, _broken, _bytes, _lag_bytes, _last_time | Archivage continu du journal (19.1.5) : état, bases suivies, sauvegardes complètes prises par le serveur ou en attente, bases dont la lignée est rompue, octets archivés, retard sur le journal, heure du dernier segment. |
Miraj_cluster_fragment_*, Miraj_cluster_sync_*, Miraj_cluster_unlogged_rebootstraps | Édition Cluster : lectures et écritures de partitions tenues par un autre nœud, attentes de l'accusé des secondaires synchrones, réamorçages (chapitre 17). |
Miraj_change_events_published, _buffered, _buffer_bytes, _evicted, _resyncs, _bulk, _listeners, _waits, _last_seq | Événements de changement : publiés, gardés en mémoire (nombre et octets), évincés, RESYNC rendus, BULK, abonnements actifs, WAIT FOR CHANGES exécutés, dernier numéro publié (chapitre 21). Compteurs propres à chaque nœud d'un cluster. |
Cette liste s'enrichira au fil des versions ; consultez SHOW STATUS sans filtre pour la liste complète de l'instance en service.
16.6.2 information_schema#
information_schema (lecture seule) donne une vue structurée utile à l'administration, notamment : SCHEMATA, TABLES, COLUMNS, STATISTICS, VIEWS, TABLE_CONSTRAINTS, KEY_COLUMN_USAGE, REFERENTIAL_CONSTRAINTS, ainsi que les tables de privilèges USER_PRIVILEGES, SCHEMA_PRIVILEGES, TABLE_PRIVILEGES, APPLICABLE_ROLES, ENABLED_ROLES. Un compte ne voit, dans SHOW DATABASES, SHOW TABLES et information_schema, que ce qu'il a le privilège d'atteindre.
En édition Cluster, information_schema.MIRAJ_NODES et information_schema.MIRAJ_REPLICATION complètent SHOW CLUSTER STATUS pour le suivi de la réplication (voir 16.1.4).
Autres vues de supervision : PROCESSLIST (comme SHOW PROCESSLIST), INNODB_TRX (transactions ouvertes), PARTITIONS, ENDPOINTS et ENDPOINT_PRIVILEGES (API REST, chapitre 24), ROUTINE_PRIVILEGES (droits par procédure ou fonction, chapitre 15), ENGINES, COLLATIONS, COLLATION_CHARACTER_SET_APPLICABILITY, GLOBAL_VARIABLES / SESSION_VARIABLES (comme SHOW VARIABLES, noms en majuscules), GLOBAL_STATUS / SESSION_STATUS (comme SHOW STATUS), KEYWORDS (mots-clés de la référence et de l'analyseur de MIRAJ, réunis) et SQL_FUNCTIONS (fonctions réellement disponibles, celles propres à MIRAJ comprises). FILES, TABLESPACES, INNODB_LOCKS et USER_STATISTICS existent pour les outils mais restent vides (@@userstat vaut OFF, comme la référence par défaut).
Les bases performance_schema et sys existent aussi, en lecture seule (écriture d'une table : 1142 ; création d'une table ou d'une vue, CREATE / DROP DATABASE : 1044), pour les outils d'administration. Comme dans la référence, ces deux bases demandent un privilège : un compte sans droit sur elles ne les voit pas (SHOW DATABASES, information_schema) et ne peut les lire (1142, USE : 1044) ; GRANT SELECT ON performance_schema.* TO … les ouvre.
performance_schema offre global_variables, session_variables, global_status, session_status et threads (une ligne par session, vue comme SHOW PROCESSLIST), et l'instrumentation des instructions, tenue en mémoire depuis le démarrage du serveur (@@performance_schema vaut ON) :
events_statements_summary_by_digest: une ligne par empreinte et par base courante. L'empreinte (DIGEST, 32 chiffres hexadécimaux) est celle du texte normalisé de l'instruction (DIGEST_TEXT) : littéraux et paramètres remplacés par?, mots-clés en majuscules, identifiants entre accents graves, commentaires retirés, listes de valeurs réduites à(...). Deux instructions qui ne diffèrent que par leurs valeurs se cumulent donc : exécutions (COUNT_STAR), durées en picosecondes (SUM_,MIN_,AVG_,MAX_TIMER_WAIT,SUM_LOCK_TIME), erreurs, avertissements, lignes affectées, envoyées et examinées, lectures complètes (SUM_NO_INDEX_USED,SUM_SELECT_SCAN), tris, première et dernière exécution. Aucun littéral n'y est gardé (ni mot de passe, ni donnée). Le texte normalisé est coupé à 1024 octets ; au-delà de 10 000 empreintes, les suivantes sont cumulées sur une ligne sans empreinte (DIGESTàNULL).accounts,users,hosts: sessions ouvertes et connexions depuis le démarrage, par compte, par utilisateur et par hôte.table_io_waits_summary_by_index_usage: une ligne par index de chaque table, avec le nombre de lectures qui sont passées par lui (COUNT_STAR,COUNT_READ,COUNT_FETCH; durées et écritures à 0).
TRUNCATE TABLE remet à zéro ces résumés (privilège DROP sur la table), comme la référence, et global_status comme FLUSH STATUS ; les autres tables (session_status comprise) refusent toute écriture. Les tables de réglage et d'historique (setup_*, events_waits_*, events_statements_current, _history, _history_long, events_stages_history_long, session_connect_attrs, résumés par table, par fichier et de la mémoire) existent avec leurs colonnes mais restent vides.
-- Les dix instructions qui ont coûté le plus de temps depuis le démarrage
SELECT query, db, exec_count, total_latency, avg_latency, rows_examined_avg, full_scan
FROM sys.statement_analysis LIMIT 10;
-- Index jamais lus depuis le démarrage
SELECT * FROM sys.schema_unused_indexes;sys offre version, sys_config, processlist et session (sessions ouvertes : instruction en cours, sa durée, ses lignes examinées et son attente de verrous ; dernière instruction terminée, sous son texte normalisé sans littéral, et sa durée), statement_analysis (les empreintes de la plus coûteuse à la moins coûteuse, durées écrites en clair : 1.50 ms), user_summary et host_summary (instructions, durée cumulée et moyenne, lectures complètes, connexions ouvertes et totales par utilisateur et par hôte) et schema_unused_indexes (index jamais lus depuis le démarrage, clés primaires exceptées — à lire après une période d'activité représentative). schema_table_statistics, schema_index_statistics et les vues memory_* restent vides ; fichiers et mémoire ne sont pas relevés (colonnes à NULL).
Une base créée par une ancienne version sous le nom sys ou performance_schema serait masquée par la base virtuelle : son répertoire est renommé au démarrage (sys_base, performance_schema_base), elle reste accessible sous ce nom et le journal du serveur le signale.
MIRAJ_PARALLELISM donne une ligne : édition, fils du budget et fils occupés, taille des morceaux (MORSEL_ROWS), requêtes parallèles, en série ou réduites et part équitable, les mêmes chiffres que les compteurs Miraj_parallel_*.
Tables propres à MIRAJ pour la concurrence : MIRAJ_CONCURRENCY (modèle en service, transactions actives, filigrane de purge, transaction la plus ancienne et compteurs de la mise à jour différée), MIRAJ_VERSIONS (versions en attente, par table) et MIRAJ_DEFERRED_UPDATE (mise à jour différée, une ligne de compteurs cumulés depuis le démarrage) :
SELECT INTENTS_RECORDED, ROWS_APPLIED, COMMIT_FAILURES, FAILED_READ_VALIDATION,
NORMAL_KEY, NORMAL_TRIGGER
FROM information_schema.MIRAJ_DEFERRED_UPDATE;INTENTS_RECORDED compte les UPDATE différés, ROWS_APPLIED les lignes écrites au COMMIT, IMAGES_MATERIALIZED les UPDATE différés rattrapés par une écriture ordinaire de la même transaction ; COMMIT_FAILURES les COMMIT refusés d'une transaction qui avait des UPDATE différés, détaillés par cause (FAILED_WITNESS : ligne changée de sorte que le WHERE ou une colonne lue par un déclencheur AFTER UPDATE ne vaut plus ; FAILED_ROW_GONE, FAILED_CONCURRENT_WRITER, FAILED_WARNING, FAILED_TABLE_REDEFINED, FAILED_ERROR, FAILED_READ_VALIDATION : la transaction avait lu une ligne modifiée depuis) ; ENGINE_RETRIES les instructions en auto-validation rejouées par le moteur après un conflit ; les colonnes NORMAL_* les UPDATE d'une session à ON qui n'ont pas pu être différés, par raison (SESSION, FORM, TABLE, TRIGGER, KEY, ROW_COUNT, ROW, CALCULATION). Un FAILED_READ_VALIDATION élevé signale des transactions qui lisent une ligne avant de la mettre à jour (voir 14.2).
16.6.3 Journalisation#
--log(oulogdans le fichier XML) tient à jour<root>\miraj\server.log: ce fichier ne reçoit, horodatées, que les erreurs SQL renvoyées aux clients (avec la commande en cause), les pannes internes (paniques capturées, jamais transmises à l'appelant) et les problèmes de fonctionnement du serveur. Les requêtes qui réussissent n'y apparaissent pas ; les connexions et les erreurs sont en revanche aussi affichées sur la sortie standard.- Les mots de passe et les clés de chiffrement ne sont jamais écrits en clair dans ces journaux : le texte d'une commande y est gardé avec
IDENTIFIED BY '<secret>',PASSWORD('<secret>'),SET PASSWORD … = '<secret>',AES_ENCRYPT(x, '<secret>')… Il en va de même pour la colonneInfodeSHOW PROCESSLISTet deinformation_schema.PROCESSLIST, visible des autres comptes. La consolemiraj-clin'écrit pas ces commandes dans son historique sur disque (elles restent rappelables pendant la session). --slow-query-log(ouslow_query_log/slow_query_log_file) consigne dans<root>\miraj\slow.log(ou le fichier choisi) chaque instruction plus longue que--long-query-timesecondes, avec le volume envoyé au client (Bytes_sent).SET GLOBAL log_output = 'TABLE'bascule ce journal vers la tablemiraj.slow_log;FLUSH SLOW LOGSrouvre le fichier après une rotation externe.- Au démarrage (
--slow-query-log-fileou fichier XML), le chemin du journal lent est libre, absolu ou relatif au dossier de données. En cours d'exécution,SET GLOBAL slow_query_log_file = '…'est confiné : le chemin doit être relatif, sans.., lecteur ni:, et son dossier doit déjà exister dans le dossier de données (à défaut, dans le dossier du fichier fixé au démarrage par un chemin absolu) sans en sortir par un lien. Un lien symbolique, un dossier, un fichier du moteur (.mrj,.mrl…) ou le dossier des clés du coffre sont refusés. Tout refus renvoie l'erreur 1231 ;SHOW WARNINGSen donne le motif. Pour écrire le journal ailleurs, fixez le chemin au démarrage.
16.6.4 FLUSH#
FLUSH [NO_WRITE_TO_BINLOG | LOCAL] option [, option] … demande le privilège RELOAD (1227 sinon) et valide implicitement la transaction ouverte, comme la référence. Options :
| Option | Effet dans MIRAJ |
|---|---|
TABLES (ou TABLE) | Point de sauvegarde : tables modifiées écrites dans leurs fichiers (.mrj…), journaux vidés sur disque ; résultats gardés des vues ordinaires oubliés (ceux des vues CACHED restent figés jusqu'au prochain REFRESH VIEW). Avec une liste FLUSH TABLES t1, t2, seules les bases de ces tables (une table absente est ignorée) |
TABLES WITH READ LOCK | Verrou global de lecture (voir ci-dessous), puis point de sauvegarde de toutes les bases ; AND DISABLE CHECKPOINT accepté |
TABLES t1, t2 WITH READ LOCK / TABLES t FOR EXPORT | Bases des tables sauvegardées, puis tables tenues en lecture comme par LOCK TABLES t1 READ, t2 READ (lecture des seules tables nommées, écriture : 1099, autres tables : 1100), journaux vidés ; libéré par UNLOCK TABLES. Privilèges en plus de RELOAD : LOCK TABLES sur la base et SELECT sur chaque table |
PRIVILEGES | Sans effet : les droits s'appliquent dès l'instruction qui les change |
HOSTS | Débloque les adresses bloquées par max_connect_errors (voir 16.5.2) |
STATUS (GLOBAL STATUS, SESSION STATUS) | Aborted_connects et Connection_errors_max_connections remis à zéro, Max_used_connections ramené aux connexions ouvertes |
LOGS, SLOW LOGS, ERROR LOGS, BINARY LOGS | LOGS et SLOW LOGS rouvrent le journal des requêtes lentes ; LOGS et ERROR LOGS rouvrent le journal du serveur (<root>\miraj\server.log, option --log) : rotation par déplacement du fichier puis FLUSH LOGS ; LOGS et BINARY LOGS font tourner le journal binaire s'il est tenu (--log-bin, chapitre 17), permis sous le verrou global de lecture |
SSL | Relit le certificat et la clé TLS (--tls-cert, --tls-key) : les connexions suivantes du port principal reçoivent le nouveau certificat, les connexions ouvertes gardent le leur. Fichier illisible ou refusé : erreur 1105, l'ancien certificat reste en usage. Sans TLS, sans effet |
QUERY CACHE, RESET QUERY CACHE | FLUSH QUERY CACHE (défragmentation dans la référence) est sans effet ; RESET QUERY CACHE oublie les résultats gardés des vues ordinaires |
ENGINE, GENERAL, RELAY LOGS, USER_RESOURCES, DES_KEY_FILE, OPTIMIZER_COSTS, CLIENT_STATISTICS, TABLE_STATISTICS, INDEX_STATISTICS, USER_STATISTICS, USER_VARIABLES, CHANGED_PAGE_BITMAPS, MASTER, SLAVE, THREADS | Acceptés sans effet (le moteur n'a pas la mécanique correspondante) ; BINARY LOGS DELETE_DOMAIN_ID = (…), RELAY LOGS 'connexion', … FOR CHANNEL 'canal' admis |
TABLES s'emploie seul (FLUSH TABLES, STATUS : 1064, comme la référence) ; une option inconnue donne 1064.
Verrou global de lecture. FLUSH TABLES WITH READ LOCK attend la fin des écritures déjà commencées (au plus lock_wait_timeout secondes, puis 1205), écrit les tables sur disque et garde le verrou jusqu'à UNLOCK TABLES ou la fin de la session. Pendant ce temps :
- toutes les sessions lisent librement ;
- toute écriture d'une autre session —
INSERT,UPDATE,DELETE,LOAD DATA, DDL, comptes etGRANT,LOCK TABLES … WRITE,OPTIMIZE/REPAIR TABLE,RESTORE, et leCOMMITd'une transaction qui a écrit — attend sans rien tenir, puis échoue en 1205 au-delà delock_wait_timeout(SHOW PROCESSLIST:Waiting for global read lock) ; les tables temporaires de la session restent modifiables ; - la session qui tient le verrou reçoit 1223 si elle écrit ; elle peut prendre en plus
LOCK TABLES … READ, etUNLOCK TABLESrend les deux. SousLOCK TABLES,FLUSH TABLES WITH READ LOCKest refusé (1192).
Plusieurs sessions peuvent tenir le verrou en même temps. C'est ce qu'emploient les outils de sauvegarde qui copient des fichiers ou lisent plusieurs bases dans un état figé :
FLUSH TABLES WITH READ LOCK;
BACKUP DATABASE gestion TO 'gestion-fige'; -- permis : BACKUP lit
-- … copie des fichiers, lecture des positions …
UNLOCK TABLES;Édition Cluster : le verrou est local au nœud. Sur un primaire, il retient les écritures des clients de ce nœud, pas l'application du journal sur les secondaires ; sur un secondaire, il ne retient pas l'application du journal reçu du primaire.
Journal binaire (--log-bin) : ses écritures se font à la validation, sous l'inscription de l'écriture qui valide ; le verrou les arrête donc au même point que les tables, et la position lue par SHOW MASTER STATUS sous le verrou ne bouge plus jusqu'à UNLOCK TABLES. Sur un réplica (CHANGE MASTER TO, chapitre 17), le fil SQL est retenu, comme dans la référence, mais groupe par groupe : un groupe en cours d'application est terminé avant que le verrou soit accordé, le suivant attend sans délai ni erreur (SHOW SLAVE STATUS, Slave_SQL_Running_State : Waiting for global read lock) ; STOP SLAVE interrompt cette attente et rend le groupe à la file. Une sauvegarde prise sous le verrou sur un réplica voit donc un état figé, à la position @@gtid_slave_pos lue au même moment.
16.7 Sauvegarde et restauration#
Le serveur sauvegarde une base à chaud, sans l'arrêter. Démarrez-le avec un dossier de sauvegardes (--backup-dir, voir 16.1.3), puis :
BACKUP DATABASE gestion TO 'gestion-2026-09-24';
RESTORE DATABASE gestion_copie FROM 'gestion-2026-09-24';La copie est cohérente, avec toutes les transactions validées jusqu'à un instant et aucune au-delà. Les écritures ne sont suspendues que quelques millisecondes. L'outil miraj-backup pilote ces instructions depuis une tâche planifiée, et miraj-dump exporte une base en script SQL portable, comptes compris. Tout est détaillé au chapitre 19.
Ces sauvegardes ne contiennent pas le coffre des comptes. Exportez les comptes avec miraj-dump --users, ou copiez à froid le sous-dossier miraj\ et la clé du coffre (voir ci-dessous). Leur manifeste est signé avec une clé dérivée de celle du coffre : un serveur qui a une autre clé restaure la sauvegarde avec un avertissement, un manifeste falsifié est refusé (voir 19.1.4).
Copie à froid du dossier complet, pour un changement de machine avec les comptes, par exemple :
- Arrêtez le serveur. Comme rappelé en 16.1.2,
miraj-servern'offre pas de séquence d'arrêt propre : traitez chaque arrêt comme un arrêt brutal. C'est la reprise par journal (16.4.4) qui garantit un dossier cohérent au prochain démarrage. - Copiez le dossier de données (
--root) dans son intégralité : bases (.mrj,.bmrj,.dmrjet.dbmrjdes tables disque,journal.mrl), sous-dossiermiraj\(comptes, journaux internes) et fichiers de configuration XML éventuels. - Copiez séparément la clé du coffre des comptes si elle est nécessaire à la restauration sur une autre machine ou sous un autre compte Windows (voir 16.5.1) : elle n'est pas dans le dossier de données.
- Pour restaurer, replacez ce dossier (et la clé, si nécessaire) à l'emplacement attendu, puis redémarrez le serveur normalement.
Pour une base intégrée (usage via miraj.dll, hors serveur réseau), la fermeture normale de l'instance écrit tout avant de rendre la main : une sauvegarde à froid après cette fermeture n'a pas à se soucier d'un arrêt brutal.
16.8 Performance : réglages à connaître#
L'exécution parallèle (éditions Entreprise et Cluster — l'édition Express exécute chaque requête sur le seul fil de sa session, et l'édition Developer limite le budget du serveur à un seul fil) répartit sur plusieurs fils les lectures volumineuses : filtres, projections, agrégation, tri, DISTINCT, jointures INNER/LEFT, et la lecture sous-jacente des UPDATE/DELETE/INSERT ... SELECT — avec, dans tous les cas, les mêmes résultats et le même ordre qu'en exécution série.
Deux réglages contrôlent ce parallélisme :
--parallel-threads <n>(serveur) : fixe le nombre total de fils que toutes les requêtes du serveur peuvent occuper ensemble. Par défaut, un fil par cœur de la machine. À réduire si le serveur partage la machine avec d'autres services, ou à ajuster si des mesures montrent une contention entre requêtes concurrentes.max_parallel_degree(variable de session) : borne le degré de parallélisme d'une session donnée, dans la limite du budget serveur ci-dessus. Utile pour réserver l'essentiel des fils à un traitement interactif tout en laissant un traitement de fond (import, recalcul en masse) se dérouler avec un degré plus faible, ou l'inverse.
EXPLAIN affiche le degré de parallélisme retenu pour une requête donnée, ce qui permet de vérifier qu'un réglage a l'effet attendu avant de le généraliser. EXPLAIN ANALYZE (ou ANALYZE, voir 9.21) exécute la requête et rend en plus les lignes et les temps réels de chaque opérateur : le moyen de repérer l'étape coûteuse d'une requête lente consignée dans le journal des requêtes lentes. Sans envoyer les lignes au client, il exécute vraiment la requête, et ANALYZE UPDATE|DELETE modifie vraiment les lignes : à lancer avec la même prudence qu'une instruction ordinaire.
Recherche plein texte : score et mémoire#
Le score de MATCH … AGAINST est celui de la référence par défaut. Pour un classement qui tient compte de la longueur des fiches (BM25, chapitre 9, §9.22), l'application pose SET miraj_ft_ranking = 'bm25' à l'ouverture de ses sessions (variable de session seulement ; miraj_ft_bm25_k1 et miraj_ft_bm25_b règlent la formule). La recherche floue (mot~1, IN FUZZY MODE) parcourt le dictionnaire de l'index à la planification : de l'ordre de la milliseconde pour 20 000 mots distincts ; miraj_ft_fuzzy_max_expansions borne le nombre de mots retenus par mot cherché. Les index FULLTEXT sont tenus en mémoire et reconstruits à l'ouverture de chaque table : compter de l'ordre de 500 Mo et 25 s par million de lignes de 56 mots, dont 4 octets par ligne pour la longueur des lignes du score BM25.
Bascule automatique entre mono-cœur et multi-cœur#
Les éditions Entreprise et Cluster basculent d'elles-mêmes entre exécution multi-cœur et exécution mono-cœur, sans réglage :
- Selon la charge. Le serveur compte les instructions en cours d'exécution. Une requête ne reçoit que sa part équitable des fils : le budget divisé par ce nombre. Seule, elle prend tous les cœurs. À deux, elle en prend la moitié. Dès qu'il y a autant d'instructions en cours que de fils, chacune s'exécute sur le seul fil de sa session, comme en mono-cœur : aucun fil supplémentaire ne vient disputer les cœurs aux autres sessions. Une session en attente (
SLEEP,WAIT FOR CHANGES, verrou de table d'une autre instruction ou d'unLOCK TABLES) ne compte pas. Les fils sont rendus dès la fin de la lecture, sans attendre que le client ait reçu tout le résultat. - Selon la requête. Une agrégation
GROUP BYtraite d'abord un morceau sur le fil de la session. Si elle y trouve presque un groupe par ligne (regroupement sur une clé), elle continue en série. Dans ce cas, fusionner les résultats partiels des fils coûterait plus que le parallélisme ne rapporte. - Selon la taille de la table. Une lecture répartie est découpée en environ 8 morceaux par fil, de 16 384 lignes au moins et de
parallel_morsel_rowslignes au plus (131 072 par défaut). Sur une table d'un million de lignes, tous les cœurs reçoivent ainsi du travail, et le morceau d'essai d'unGROUP BYn'en retarde qu'une petite part.
Les compteurs Miraj_parallel_statements_active, Miraj_parallel_fair_share et Miraj_parallel_queries_serialized_load / _downgraded / _volume (voir 16.6) montrent ces décisions. EXPLAIN indique le degré que la requête demande. Le degré qu'elle obtient à l'exécution dépend de la charge du moment. --parallel-threads et max_parallel_degree restent des plafonds : SET max_parallel_degree = 1 force toujours l'exécution en série d'une session.
Pour la volumétrie des BLOB, --lob-threshold et --lob-cache (voir 16.1.3 et 16.3) influent aussi sur la performance : un seuil plus bas déporte plus de valeurs hors des fichiers de table (utile si les lignes doivent rester compactes en mémoire), un cache plus grand réduit les lectures répétées de BLOB volumineux au prix de la mémoire qu'il occupe.
16.9 Gestionnaire graphique Miraj Server Manager#
Sous Windows, Miraj Server Manager (miraj-manager.exe, installé par l'assistant de Miraj Express) rassemble les gestes courants d'administration d'un serveur de la machine, depuis une icône de la zone de notification :
- démarrer, arrêter et redémarrer le serveur, par la tâche planifiée « Miraj Express » de l'installation ou en lançant
miraj-server.exe --root <données> --log; - suivre son état, sa consommation de processeur, de mémoire et de disque, avec les courbes des dix dernières minutes ;
- suivre les requêtes : nombre total (
Questions), requêtes par seconde, requêtes en cours (SHOW FULL PROCESSLIST), requêtes lentes (Slow_queries,miraj.slow_log) et réglage du journal des requêtes lentes ; - faire une sauvegarde complète (
BACKUP ALL DATABASES) vers un dossier choisi, immédiate ou planifiée, avec un compte dédiémiraj_backuplimité àBACKUP_ADMIN.
Ses textes suivent la variable language de miraj_config.xml. Son fonctionnement est décrit au chapitre 22.
16.10 Instance en langage PostgreSQL#
Une instance MIRAJ parle un seul langage SQL, choisi au démarrage par l'élément POSTGRESQL de sql_mode :
- sans lui (défaut), langage MIRAJ et protocole hérité : Gestium,
miraj-cli, les outils graphiques et pilotes du protocole hérité ; - avec lui, langage et protocole PostgreSQL :
psql, psycopg2/psycopg, psqlODBC, Npgsql, pgjdbc et les outils qui s'appuient sur eux.
Les outils de MIRAJ (30.12), le pilote ODBC de MIRAJ (chapitre 29) et la bibliothèque Python miraj (27.12) reconnaissent le langage de l'instance à la connexion et parlent les deux.
Le choix se fait par --sql-mode POSTGRESQL,STRICT_TRANS_TABLES, par <sql_mode>POSTGRESQL,STRICT_TRANS_TABLES</sql_mode> dans miraj_config.xml, par le choix Langage SQL de l'éditeur de configuration (qui ajoute ou retire le seul élément POSTGRESQL sans toucher aux autres), par la question de l'assistant d'installation ou, sous macOS, par le choix Langage SQL de l'instance de la première configuration dans Miraj Server Manager. Changer de langage demande un redémarrage ; les bases et leurs données restent valables. Le démarrage l'annonce :
MIRAJ 1.0.0 Entreprise - serveur console sur 127.0.0.1:7007, langage PostgreSQL, dossier "D:\donnees", 10 fils, licence ….16.10.1 Un seul port#
Le protocole PostgreSQL est servi sur le port principal (--port, 7007 par défaut), à la place du protocole hérité : il n'y a pas de second port. miraj-proxy (en-tête PROXY v2 d'un relais de confiance, --proxy-protocol-from) et le pare-feu n'ont rien à changer. Les règles de connexion sont celles du protocole hérité : connect_timeout, wait_timeout, max_connections, blocage d'une adresse après max_connect_errors échecs, max_allowed_packet, KILL, mode local seul.
Un client qui se trompe de langage est fermé avec un message clair sur la sortie standard et dans server.log :
- client du protocole hérité (Gestium, un outil MIRAJ lancé avec
--protocol miraj…) sur une instance PostgreSQL : il attend la salutation du serveur, qui attend son message de démarrage ; au bout deconnect_timeout, la connexion est fermée avec « client sans message de démarrage PostgreSQL (langage de l'instance : PostgreSQL, voir sql_mode) » ; - client PostgreSQL sur une instance MIRAJ : fermé aussitôt avec « client PostgreSQL sur une instance en langage MIRAJ (sql_mode sans POSTGRESQL) ».
Les outils de MIRAJ (miraj-cli, miraj-dump, miraj-backup, miraj-migrate, les gestionnaires, la sonde de miraj-proxy) reconnaissent eux-mêmes le langage de l'instance (--protocol auto, défaut) : leur première connexion à une instance MIRAJ est une telle sonde, fermée sans être comptée dans Aborted_connects (30.12).
16.10.2 Chiffrement et authentification#
- TLS : avec
--tls-certet--tls-key, le serveur accepte la demande de chiffrement des clients (sslmode=prefer,require,verify-ca,verify-full) avec le même certificat que le protocole hérité ; sans certificat, il la décline et un client ensslmode=prefercontinue en clair. TLS exigé (défaut dès qu'un certificat est donné, sauf--allow-plain-with-tls) : une connexion en clair est refusée (FATAL 28000). Comptes : les mêmes que dans le langage MIRAJ (
CREATE USER, hôtes, rôles, verrouillage). Le mécanisme d'authentification dépend du compte :- SCRAM-SHA-256 (
password_encryption = scram-sha-256) pour tout compte dont le mot de passe a été défini parCREATE USER … IDENTIFIED BY,ALTER USER … IDENTIFIED BYouSET PASSWORD, dans l'un ou l'autre langage, ainsi que pourroot(mot de passe initial) : le serveur garde, à côté du vérificateur habituel, un vérificateur SCRAM (sel aléatoire, 4 096 itérations) dans le coffre chiffré des comptes. Le mot de passe ne circule pas : la connexion est acceptée avec ou sans TLS, depuis toute adresse. Le serveur n'annonce queSCRAM-SHA-256; un client qui exige la liaison au canal TLS (channel_binding=require) est refusé (FATAL 28000),channel_binding=prefer(défaut) fonctionne. - Mot de passe en clair (
AuthenticationCleartextPassword) pour un compte sans vérificateur SCRAM : mot de passe donné par son empreinte (IDENTIFIED BY PASSWORD '*…'), ou défini avant la prise en charge de SCRAM (dossier de données plus ancien). Il n'est demandé que sous TLS ou depuis la boucle locale : une connexion en clair depuis une autre machine, ou relayée par un relais de confiance, est refusée avant que le mot de passe ne circule (FATAL 28000, avec un message qui invite à redéfinir le mot de passe). Pour donner un vérificateur SCRAM à un tel compte, il suffit de redéfinir son mot de passe (ALTER USER 'nom'@'hôte' IDENTIFIED BY '…', ouSET PASSWORDpar le titulaire) ; l'empreinte seule ne le permet pas. - Aucun pour un compte sans mot de passe : accepté sans rien demander.
Mot de passe faux :
FATAL 28P01, compté pour l'adresse comme dans le protocole hérité (ralentissement, blocage aprèsmax_connect_errors). Un compte inconnu reçoit le même échange SCRAM (sel stable dérivé de son nom) et le même refus28P01: rien ne distingue un compte inconnu d'un mot de passe faux. Seul un compte existant sans vérificateur SCRAM, contacté en clair depuis une autre machine, se reconnaît à son refus28000. Ni le mot de passe, ni la preuve, ni les messages SCRAM ne sont écrits dansserver.log; le journal note le mécanisme employé (compte app@% (SCRAM-SHA-256, TLS)).rolpasswordreste masqué (********danspg_roles, NULL danspg_authid).- SCRAM-SHA-256 (
- Base de connexion (
dbname) :miraj,postgresou le nom de l'utilisateur (défauts des clients) sont ignorés ; le nom d'une base MIRAJ en fait la base courante ; une base inconnue donne un avis (NOTICE 3D000) et la connexion s'ouvre sans base courante.
16.10.3 Se connecter avec psql#
$env:PGPASSWORD = "mot de passe"
psql -h 127.0.0.1 -p 7007 -U root -c "SELECT 1"
psql "host=serveur.exemple port=7007 user=root dbname=gestion sslmode=require"Une requête envoyée par psql -c ou saisie dans la console peut contenir plusieurs instructions ; chacune rend son résultat et son étiquette (SELECT 3, INSERT 0 1, UPDATE 2, CREATE TABLE…). Les avertissements arrivent en WARNING ou NOTICE, les erreurs avec un SQLSTATE PostgreSQL (42P01 table absente, 42703 colonne inconnue, 23505 doublon, 42601 syntaxe, 3D000 base inconnue…). Ctrl-C annule la requête en cours (57014, comme KILL QUERY). Dans un bloc BEGIN … COMMIT, une erreur met le bloc en échec : seules ROLLBACK (ou COMMIT, qui annule alors) et ROLLBACK TO SAVEPOINT sont acceptées ensuite, les autres instructions recevant 25P02.
\copy charge ou écrit un fichier du poste client (texte ou CSV) par COPY … FROM STDIN et COPY … TO STDOUT (30.11) :
boutique=# \copy articles (code, nom, prix) from 'articles.csv' with (format csv, header)
COPY 1250
boutique=# \copy (SELECT * FROM ventes WHERE jour >= '2026-10-01') to 'ventes-octobre.txt'
COPY 312Le serveur ne travaille qu'en UTF-8 (client_encoding = UTF8) : sous Windows, passez la console en UTF-8 (chcp 65001) ou fixez PGCLIENTENCODING=UTF8, sans quoi un texte accentué saisi dans une autre page de codes est refusé (22021).
Les commandes de description de psql lisent le catalogue pg_catalog (30.9) : \l montre l'unique base PostgreSQL miraj, \dn les bases de MIRAJ (chacune est un schéma), \dt, \dv, \di, \ds et \d les tables, vues, index et séquences de la base courante (celle du paramètre dbname, ou de SET search_path), \d table et \d+ table leurs colonnes (types PostgreSQL, valeurs par défaut, identité), index, contraintes et clés étrangères, \du les comptes, \df les routines, \dx l'extension vector, \dp les tables (sans droits détaillés), \x l'affichage étendu. \dt boutique.* liste les tables d'une autre base.
boutique=# \d clients
Table « boutique.clients »
Colonne | Type | ... | NULL-able | Par défaut
-----------+-----------------------+-----+-----------+----------------------------------
id | integer | | not null | generated by default as identity
nom | character varying(80) | | not null |
solde | numeric(12,2) | | | 0
Index :
"clients_pkey" PRIMARY KEY, btree (id)
Référencé par :
TABLE "commandes" CONSTRAINT "commandes_ibfk_1" FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE16.10.4 Pilotes : protocole étendu, Npgsql, pgjdbc#
Les pilotes qui préparent leurs requêtes (Npgsql, pgjdbc, et toute bibliothèque qui envoie des paramètres $1, $2…) utilisent le protocole étendu : instructions préparées nommées ou anonymes (Parse), portails (Bind), description (Describe), exécution (Execute), fermeture (Close), Sync et Flush.
- Paramètres
$1,$2… : un même numéro peut revenir plusieurs fois et dans le désordre (WHERE a = $1 OR b = $1). Chaque valeur est liée par le moteur, jamais recopiée dans le texte SQL. Valeurs en texte ou en binaire :int2/int4/int8,oid,float4/float8,bool,numeric,text/varchar/bpchar/name,bytea,date,time,timestamp,timestamptz(instant ramené au fuseau de la session),uuid,json/jsonb; NULL. Une date-heure en texte suivie d'un décalage (2026-10-06 12:30:00+02, comme pgjdbc envoiesetTimestamp) le perd, comme'…'::timestampsur le serveur de référence. - Type des paramètres (ParameterDescription) : celui que le client impose, sinon
text. - Résultats en texte ou en binaire, au choix du client pour chaque colonne : entiers, flottants,
bool,numeric(format binaire exact, jusqu'aux 18 chiffres desDECIMAL),bytea, textes,date,time,timestamp,timestamptz(texte suivi du décalage de la session, binaire en microsecondes UTC),uuid. Une valeur qui ne se convertit pas dans le type annoncé au client est refusée (22003,22P02) plutôt qu'envoyée fausse ; une date zéro (0000-00-00) n'a pas de forme binaire (22008). - Lecture par morceaux (pgjdbc
setFetchSizedans une transaction) : le résultat est gardé en mémoire par le serveur et envoyé par paquets de la taille demandée. - Erreurs : après une erreur, les messages suivants sont ignorés jusqu'au Sync, comme sur le serveur de référence ; dans un bloc
BEGIN, le bloc passe en échec. - Lots (pgjdbc
executeBatch,NpgsqlBatch) : les écritures envoyées entre deux Sync hors d'un bloc forment une transaction, validée au Sync ou annulée entièrement si l'une échoue. - Annulation :
NpgsqlCommand.Cancel(),Statement.cancel()et Ctrl-C interrompent aussi une requête préparée (57014). RETURNING: Describe d'une instructionINSERT,UPDATEouDELETEà clauseRETURNINGdécrit ses colonnes ;getGeneratedKeysde pgjdbc (qui ajouteRETURNING *ouRETURNING "id") etExecuteReaderde Npgsql lisent les lignes écrites, l'étiquette restant celle de l'écriture (INSERT 0 1).COPY: en requête simple seulement (CopyInResponse, CopyData, CopyDone, CopyFail ; CopyOutResponse, CopyData, CopyDone) :CopyManagerde pgjdbc,BeginTextImportetBeginTextExportde Npgsql,copy_from,copy_toetcopy_expertde psycopg2. Format binaire (BeginBinaryImportde Npgsql) non pris en charge.- Catalogue : les colonnes reprises d'une table annoncent l'OID de leur table et leur numéro (RowDescription, comme
pg_classetpg_attributeles donnent) ; Npgsql charge à l'ouverture les types depg_type(types de base, tableaux, énumérations), pgjdbc et DBeaver lisentpg_namespace,pg_class,pg_attribute,pg_indexetpg_constraint(voir 30.9). - Paramètres de session : les
SETenvoyés par les pilotes (extra_float_digits,application_name,DateStyle,TimeZone,client_encoding…) sont acceptés et lisibles parSHOW;client_encodingresteUTF8,DateStyleISO.SET search_path,BEGIN ISOLATION LEVEL …,SET SESSION CHARACTERISTICS AS TRANSACTION …etSHOW TRANSACTION ISOLATION LEVEL(NpgsqlBeginTransaction, pgjdbcsetTransactionIsolation) sont lus par la grammaire PostgreSQL (chapitre 30) ;DEALLOCATEetDISCARD ALLlibèrent aussi les instructions préparées du protocole étendu.
Pilotes essayés :
| Pilote | Version | État |
|---|---|---|
| Npgsql (.NET 8) | 10.0.3 | Open (types chargés depuis pg_type), ExecuteScalar, commandes paramétrées typées (int, decimal, date, timestamp, bool, text, bytea, NULL), commande préparée réutilisée, transaction, NpgsqlBatch, annulation ; GetSchema (Databases, Schemata, Tables, Views, Columns, Indexes, IndexColumns, Constraints, PrimaryKey, UniqueKeys, ForeignKeys, ConstraintColumns, Users, DataTypes), GetColumnSchema ; ExecuteReader sur INSERT … RETURNING, ON CONFLICT, BeginTextImport (et son Cancel), BeginTextExport |
| pgjdbc (Java 8) | 42.7.8 | getConnection, PreparedStatement typé, instructions préparées côté serveur (prepareThreshold), lots, setFetchSize, isolement ; DatabaseMetaData (getSchemas, getTables, getColumns, getPrimaryKeys, getImportedKeys, getExportedKeys, getIndexInfo, getTypeInfo, getBestRowIdentifier, getTablePrivileges), ResultSet modifiable (updateRow) ; getGeneratedKeys (RETURNING), CopyManager.copyIn / copyOut en texte et CSV |
| psycopg2 | 2.9.13 | requêtes paramétrées, littéraux typés ('2026-10-06'::date, '\x00'::bytea), curseurs nommés (DECLARE … CURSOR, FETCH FORWARD n) ; RETURNING, copy_from, copy_to, copy_expert |
| psql | 18 | requêtes, scripts PostgreSQL ordinaires (SERIAL, ::, ILIKE, vues), sslmode=require, Ctrl-C, \l, \dn, \dt, \dv, \di, \ds, \df, \du, \dx, \dp, \d, \d table, \d+ table, \x, SHOW ALL, \copy dans les deux sens |
DBeaver passe par pgjdbc : son navigateur (schémas, tables, colonnes, clés, index) et l'édition des lignes reposent sur les métadonnées essayées ci-dessus.
await using var conn = new NpgsqlConnection("Host=serveur;Port=7007;Username=root;Password=…;Database=gestion");
await conn.OpenAsync();
await using var cmd = new NpgsqlCommand("SELECT nom, prix FROM articles WHERE prix > $1", conn);
cmd.Parameters.Add(new NpgsqlParameter { Value = 10.5m, NpgsqlDbType = NpgsqlDbType.Numeric });16.10.5 Ce qui est disponible à ce stade#
Le langage PostgreSQL comprend aujourd'hui :
- protocole simple et protocole étendu, résultats en texte ou en binaire, types annoncés par leur OID PostgreSQL (
int2/int4/int8,numeric,float4/float8,bool,text/varchar/bpchar,date,time,timestamp,timestamptz,interval,bytea,json/jsonb,uuid,bit/varbit, énumérations, tableaux{…}d'une expression, et pour le catalogueoid,name,"char") ; les avis (NOTICE,WARNING) d'une instruction qui échoue sont envoyés avant son erreur ; - le catalogue
pg_cataloget les fonctions de PostgreSQL (version(),format_type,pg_get_indexdef,::regclass…) : commandes\dde psql, métadonnées de pgjdbc et de DBeaver, types etGetSchemade Npgsql (30.9) ; - la grammaire PostgreSQL (
"x",'…'standard,::,$1,ILIKE,FETCH FIRST,SERIAL,SET search_path, curseurs…), avec les extensions de MIRAJ (SHOW TABLES,USE, index vectoriels,MATCH … AGAINST…) ; la syntaxe propre à MIRAJ (accents graves,LIMIT a, b…) y est refusée : voir le chapitre 30 ; - l'authentification SCRAM-SHA-256 (16.10.2) ;
INSERT … RETURNING,UPDATE … RETURNING,DELETE … RETURNING,INSERT … ON CONFLICT,COPY … FROM STDIN/TO STDOUTen texte et en CSV, etCOPY … TO 'fichier'sur le serveur (30.11) ;- les fonctions, procédures, déclencheurs et blocs anonymes
DOécrits en PL/pgSQL ou en SQL (manuel du langage PostgreSQL, chapitre 40) ; - les outils MIRAJ (
miraj-clien mode réseau,miraj-dump,miraj-backup,miraj-migrate, gestionnaires, installable, sonde demiraj-proxy), protocole reconnu à la connexion, et les clusters en langage PostgreSQL (30.12) ;