En français – Version 2025
1. Introduction
Dolibarr est un ERP / CRM open‑source très répandu pour les PME, les associations et les auto‑entrepreneurs. Sa simplicité d’installation masque toutefois des exigences de performance lorsqu’il est couplé à un Système de Gestion de Base de Données relationnelle (SGBD) MySQL ou MariaDB.
En production, les administrateurs rencontrent régulièrement : 1. Des temps de réponse qui gonflent avec le nombre d’utilisateurs.
- Des verrous et des blocages qui rendent l’interface inutilisable.
- Une consommation mémoire / disque disproportionnée.
Cet article passe en revue les erreurs les plus courantes liées à l’utilisation de Dolibarr avec MySQL/MariaDB, explique leurs causes racines, puis propose des solutions concrètes accompagnées des technologies modernes d’intégration (Docker, orchestration, caching, réplication, etc.) pour parvenir à une infrastructure stable et performante.
Objectif : fournir aux DBA, aux développeurs et aux équipes DevOps une feuille de route exhaustive pour optimiser MySQL/MariaDB lorsqu’il alimente Dolibarr, dans le respect des bonnes pratiques 2025.
2. Fondamentaux du couplage Dolibarr ↔ MySQL/MariaDB
| Élément Dolibarr | Table(s) MariaDB concernées | Rôle principal |
|---|---|---|
| Sociétés /Contacts | llx_societe, llx_contact |
Gestion des tierces parties |
| Produits | llx_categorie, llx_product, llx_product_multilang |
Catalogue et stocks |
| Factures / Devis | llx_commande, llx_facture, llx_invoice |
Comptabilité |
| Stocks / Réapprovisionnement | llx_stock, llx_stock_movement |
Gestion physique des articles |
| Paramètres | llx_admin, llx_files_* |
Configuration globale |
Ces tables sont massivement écrites (INSERT/UPDATE) lors de chaque création/modification d’enregistrement, et lues (SELECT) lors de l’affichage des listes. La combinaison d’un traffic E/S élevé et d’une croissance du volume de données crée les points de tension classiques.
3. Erreurs fréquentes et diagnostics
3.1. Erreur de connexion : «Too many connections»
- Symptôme : Dolibarr affiche “Can’t connect to MySQL server” ou “Too many connections” dès le pic d’activité.
- Cause : Le pool de connexions de Dolibarr utilise, par défaut, une connexion persistante par script PHP. En environnement partagé ou avec de multiples workers (NGINX php-fpm), le nombre de connexions simultanées dépasse la valeur
max_connectionsdu serveur MySQL. - Diagnostic rapide :
mysqladmin -u root -p processlist | grep -c 'Sleep'
# ou directement dans la table information_schema.processlist
3.2. Verrous bloquants (deadlocks) sur llx_facture
- Symptôme : Intermittence lors de la sauvegarde d’une facture ; le script se bloque pendant plusieurs secondes ou minutes.
- Cause : Des requêtes d’UPDATE simultanées sur la même ligne de facture sans index dédié, combinées à un transaction isolation mal réglé (par défaut
REPEATABLE READ). - Diagnostic :
SHOW ENGINE INNODB STATUS\G -- recherche de "LATEST DETECTABLE DEADLOCK"
3.3. Table « llx_product » en plein expansion
- Symptôme : Augmentation progressive de la taille de la table, ralentissement des recherches par libellé.
- Cause : Absence d’index sur les champs
label,reference; utilisation d’un VARCHAR trop large (ex. 255) pour un champ qui n’en nécessite pas. - Diagnostic :
SELECT TABLE_ROWS, DATA_LENGTH/1024/1024 AS size_mb
FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='llx_product';
3.4. Cache de requêtes désactivé
- Symptôme : Temps de réponse qui ne diminue jamais après les premiers appels.
- Cause : Par défaut, le cache de requêtes d’InnoDB est désactivé (
query_cache_type = 0), et le query cache du client PHP n’est pas utilisé.
3.5. Problèmes de charset & collation
- Symptôme : Erreurs de “Incorrect multi-byte sequence” ou perte de caractères spéciaux dans les libellés.
- Cause : Le tableau est créé avec
utf8mb3oulatin1alors que Dolibarr attend du UTF‑8 complet (utf8mb4).
3.6. Mauvaise configuration de innodb_log_file_size
- Symptôme : Erreurs “Log file full” ou “InnoDB: Cannot allocate memory for the buffer pool”.
-
Cause : Valeur trop petite pour le volume de commits (devis/factures créés en continu). ### 3.7. Mise à jour du schéma sans migration
- Symptôme : Crash de Dolibarr après un upgrade majeur (ex. 11.x → 12.x) dû à la suppression d’un champ renommé.
- Cause : Des scripts de mise à jour de base ne sont pas exécutés automatiquement dans un environnement Docker/Kubernetes où le conteneur DB est stateless.
4. Solutions robustes, “modernisées”
4.1. Gestion des connexions
| Action | Détails | Exemple de paramétrage |
|---|---|---|
| Pool de connexion partagé | Utiliser mysqli_pconnect() ou PDO avec ATTR_PERSISTENT => true et désactiver la persistance pour les scripts CLI (shell_exec). |
php<br> $pdo = new PDO($dsn, $user, $pass, [<br> PDO::ATTR_PERSISTENT => false,<br> PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION<br> ]);<br> |
| Limiter le nombre max de connexions | Ajuster MySQL : max_connections = 500 (ou un multiple du nombre de workers PHP-FPM). |
ini<br> [mysqld]<br> max_connections = 500<br> |
| Timeout des connexions idle | wait_timeout = 30 (ou plus bas) pour libérer les sessions inactives. |
ini<br> wait_timeout = 30<br> |
| Utiliser un middleware de pooling | ProxySQL ou MaxScale en front du serveur MySQL pour réutiliser les sockets côté application. |
proxyadmin --proxy organizar -c 100 |
4.2. Optimisation des index et du schéma
- Indexer les champs de recherche
ALTER TABLE llx_product ADD INDEX idx_product_label (label);
ALTER TABLE llx_societe ADD INDEX idx_societe_name (name); - Choisir le bon type / taille
reference:VARCHAR(30)suffit généralement.code_commission:SMALLINT UNSIGNEDsi < 65535.
- Utiliser
utf8mb4systématiquementSET NAMES utf8mb4;
ALTER TABLE llx_ ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - Réduire la taille des BLOB
- Stocker les pièces jointes dans un bucket S3 ou MinIO, et ne garder que le URL dans Dolibarr (
llx_files_*).
- Stocker les pièces jointes dans un bucket S3 ou MinIO, et ne garder que le URL dans Dolibarr (
4.3. Configuration InnoDB adaptée
| Paramètre | Valeur conseillée (pour 8 Go RAM, 1 000 QPS) | Justification |
|---|---|---|
innodb_buffer_pool_size |
4 GiB – 6 GiB | Cache des pages de données les plus fréquemment accédées. |
innodb_log_file_size |
1 GiB – 2 GiB | Accompte les gros lots d’écritures (factures). |
innodb_flush_method |
O_DIRECT |
Évite le double‑cache du système d’exploitation. |
innodb_flush_log_at_trx_commit |
2 (si la perte de 1 s de transactions est acceptable) |
Diminue le I/O disk intense. |
innodb_log_buffer_size |
256 MiB (ou 128M si < 4 Go RAM) |
Accélère les commits groupés. |
innodb_file_per_table |
ON |
Permet le recyclage indépendant des tables. |
tmp_table_size / max_heap_table_size |
64M |
Limite la création de tables temporaires en mémoire. |
Astuce : Créez un fichier
my.cnf.d/99-dolibarr.cnfavec ces paramètres et chargez‑le dans le conteneur Docker via un ConfigMap Kubernetes.
4.4. Utilisation d’un cache d’objets
- Redis ou Memcached comme cache de résultats :
$redis = new Redis();
$redis->connect('redis', 6379);
$key = 'product:'.$ref;
$product = $redis->get($key) ?: $pdo->prepare(...)->fetchAll();
$redis->setex($key, 300, $product); // 5 min TTL - Avantages :
- Décrémentation du nombre de SELECT sur
llx_product. - Gestion fine de la TTL (time‑to‑live) pour les données rarement modifiées.
- Décrémentation du nombre de SELECT sur
4.5. Isolation des transactions
- Passer à
READ COMMITTEDsi vous avez peu de deadlocks :transaction_isolation = READ-COMMITTED - Utiliser
INSERT … ON DUPLICATE KEY UPDATEpour éviter les verrous explicites sur les lignes déjà existantes.
4.6. Virtualisation & conteneurisation
| Technologie | Mode d’intégration | Points forts pour Dolibarr |
|---|---|---|
| Docker‑Compose | docker-compose.yml avec trois services : db (MariaDB 10.11), app (PHP‑8.2 + Apache), cache (Redis). |
Simplicité, isolation du réseau, sauvegarde de volumes persistants (docker volume). |
| Kubernetes | Déploiement de StatefulSet pour MariaDB, Deployment pour PHP, ConfigMap pour my.cnf et php.ini. |
Scalabilité horizontale, auto‑healing, rolling updates sans perte de donnée. |
| Helm Chart « dolibarr‑stack » | Chart officiel (maintenu par la communauté 2024‑2025) qui crée automatiquement : – Service mariadb avec replicationFactor=2 – Service redis – Service dolibarr avec autoscaling |
Bonne pratique pour les CI/CD et les environnements multi‑tenant. |
| ProxySQL + MaxScale | Side‑car proxy en front du pod DB pour le load‑balancing, le query‑rewriting (ex. SET SESSION sql_mode='STRICT_TRANS_TABLES'). |
Réduction des latences, gestion dynamique des connexions. |
Exemple de ConfigMap pour MySQL (K8s)
apiVersion: v1
kind: ConfigMap
metadata:
name: dolibarr-mariadb-options
data:
my.cnf: |
[mysqld]
innodb_buffer_pool_size = 4G innodb_log_file_size = 2G
transaction_isolation = READ-COMMITTED
max_connections = 500
wait_timeout = 30
default_storage_engine = InnoDB
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ci```
Ce ConfigMap est monté dans le conteneur MariaDB avec :
```yaml
volumeMounts:
- name: my-cnf mountPath: /etc/mysql/conf.d/dolibarr.cnf
subPath: my.cnf
4.7. Sauvegarde et restauration avec PITR (Point‑In‑Time Recovery)
- Solution : Activer le binary logging (
log_bin) et le binary log expire days (expire_logs_days = 7). -
Script de sauvegarde (Docker entrypoint) :
mysqldump -u root -p"$DB_ROOT_PASSWORD" --single-transaction --quick \
--all-databases | gzip > /backup/dump-$(date +%F-%H%M).sql.gz - Récupération :
gunzip -c dump-2025-10-30-1400.sql.gz | mysql -u root -p
Bonus : Utiliser Percona XtraBackup pour des sauvegardes « hot » sans interruption de service.
4.8. Monitoring & alerting avancés
| Outil | Métriques clés | Action automatisée |
|---|---|---|
| Prometheus + node_exporter | mysql_global_status_connections, innodb_buffer_pool_pages_dirty, php_fpm_active_processes. |
Scaling verticaux (increase max_connections) ou horizontaux (add PHP pods). |
| Grafana alert rule | mysql_global_status_deadlocks > 5 → créer ticket JIRA. |
Envoi d’un webhook vers un playbook Ansible qui recrée les index. |
| ELK (Elastic + Logstash) | Logs d’erreur MySQL ([ERROR] InnoDB: Cannot allocate memory). |
Triggers auto‑restart du pod DB. |
Dolibarr healthcheck endpoint (/ index.php?controller=alert) |
Retour HTTP 200 si DB reachable, sinon 503. | Utilisé par les orchestrateurs pour détecter les unhealthy pods. |
5. Checklist d’optimisation « Ready‑to‑Deploy »
| ✅ | Action |
|---|---|
| 1 | Créer le schéma avec utf8mb4 et appliquer les index manquants (label, reference, name). |
| 2 | Ajuster my.cnf (buffer pool 40‑70 % de la RAM, log_file_size ≥ 2 GiB). |
| 3 | Configurer le pool de connexion côté PHP (ATTR_PERSISTENT = false). |
| 4 | Déployer Redis pour le cache des fiches produits et des contacts. |
| 5 | Activer le binaire log et mettre en place une sauvegarde quotidienne + PITR. |
| 6 | Déployer via Helm/K8s (ou Docker‑Compose) avec ConfigMaps pour les options MySQL et php.ini. |
| 7 | Activer le monitoring (Prometheus, Grafana) et définir des alertes sur deadlocks, connections, buffer pool dirty pages. |
| 8 | Tester la montée en charge avec sysbench : 1000 QPS simulées sur llx_facture pendant 30 min. |
| 9 | Réaliser un benchmark : temps moyen de création d’une facture avant/après optimisation (objectif < 200 ms). |
| 10 | Documenter les paramètres choisis et les points de rupture (ex : max_connections doit être revu à chaque ajout de worker). |
6. Études de cas rapides
6.1. Cas « Shop‑Online » (200 utilisateurs simultanés)
- Problème : Après 3 mois, les rapports de performance montraient 2 s de latence lors de la génération d’un bon de commande.
- Analyse :
SELECT * FROM llx_stock WHERE fk_product = Xdéclenchait un table scan faute d’index surfk_product. - Solution :
- Ajout d’un index
INDEX idx_stock_product (fk_product). - Passage à
innodb_buffer_pool_size = 6 GiB. - Cache Redis des produits populaires (TTL = 5 min).
- Déploiement d’un Horizontal Pod Autoscaler (PHP‑FPM pods scalés à 8).
- Ajout d’un index
- Résultat : Latence ↓ à 180 ms, taux d’erreur MySQL passait de 12 % à < 0,2 %.
6.2. Entreprise « LogiCo » – besoin de haute disponibilité
- Contraintes : 99,9 % de disponibilité, récupération après sinistre < 5 min. – Architecture :
- 2 nœuds MariaDB en Galera Cluster (synchronous replication).
- Pods PHP répliqués (3 replicas) derrière NGINX Ingress.
- Redis cluster en mode cluster (sharding + HA).
- Optimisation :
innodb_flush_log_at_trx_commit = 1pour garantir la durabilité.max_connections = 800(augmenté proportionnellement). – Utilisation de ProxySQL pour répartir les lecturesSELECTsur les nœuds secondaires.
- Résultat : Temps moyen de réponse < 250 ms, aucune perte de transaction pendant les tests de basculement.
7. Bonnes pratiques – le « Framework » 2025
- Infrastructure as Code (IaC) : Utiliser Terraform ou Pulumi pour créer automatiquement les ressources (DB, Redis, volumes).
- Versioning du schéma : Intégrer la migration de Dolibarr via le script
upgrade.phpexécuté automatiquement au post‑deploy du pipeline CI/CD. - Sécurité :
- Utiliser TLS 1.3 entre l’app PHP et MariaDB (parameter
sslMode=REQUIRED). - Désactiver
local_infilesauf si indispensable.
- Utiliser TLS 1.3 entre l’app PHP et MariaDB (parameter
- Gestion des secrets : Stocker les credentials DB dans Vault ou Kubernetes Secrets, jamais en clair dans le repo Git.
- Déployer avec canary : Ajouter 1 nouveaux pods PHP sur 10 avant de basculer le trafic complet, afin de détecter d’éventuels deadlocks.
8. Conclusion
L’optimisation de MySQL/MariaDB lorsqu’il alimente Dolibarr ne réside pas dans un simple réglage de variables ; elle exige une approche systémique :
- Diagnostiquer les symptômes (connexions, verrous, taille des tables).
- Corriger le schéma (index, charset, types). – Adapter le serveur (buffer pool, log files, isolation).
- Compléter avec des couches de mise en cache et des proxies modernes.
- Déployer dans un environnement conteneurisé ou orchestré qui permet le scaling, le monitoring et la résilience.
En appliquant les solutions décrites—pool de connexions maîtrisé, index ciblés, configuration InnoDB adaptée, cache Redis, et orchestration Kubernetes—vous pouvez transformer un déploiement Dolibarr qui fonctionnait « juste » en une plateforme stable, rapide et prête à supporter des charges d’entreprise.
À retenir : la clé de la performance durable réside dans l’observabilité continue (Prometheus/Grafana) et dans la régularité des revues de configuration. Tant que vous mesurez, vous pouvez améliorer !
Ressources complémentaires
| Ressource | Lien |
|---|---|
| Dolibarr 22.0 – Documentation officielle | https://www.dolibarr.org/en/doc/ |
| MySQL 8.0 Reference Manual – InnoDB Tuning | https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html |
| MariaDB 10.11 – Optimisation avancée | https://mariadb.com/kb/en/innodb-parameters/ |
| ProxySQL – Documentation | https://proxysql.com/documentation/ |
| Helm Chart « dolibarr‑stack » (GitHub) | https://github.com/yourorg/dolibarr-helm |
| Prometheus MySQL Exporter | https://github.com/prometheus/mysqld_exporter |
N’hésitez pas à adapter ces recommandations à votre contexte : chaque environnement (on‑premise, hybride cloud, multi‑tenant) peut nécessiter des ajustements spécifiques. Bon déploiement !