technique:adminserv:etherpad:mysql

Comprendre la BDD Etherpad

docker exec -it etherpad-db bash
mysql -u etherpad etherpad-lite -sN --default-character-set=utf8 -p

Le mot de passe est normalement password2, il est défini ici (MYSQL_PASSWORD)

À ne faire que si c’est absolument nécessaire

pad.picasoft.net (`pica02`)

Mêmes étapes que précédemment, mais le mot de passe est dans /DATA/docker/services/etherpad/secrets

week.pad.picasoft.net (`pica01`)

docker exec -it weekpad-db bash
psql -U weekpad -d weekpad

Sur ce conteneur, vous êtes connecté direct en tant que root, donc psql vous demandera pas de mot de passe

La structure est hyper simple. Dans la BDD etherpad-lite, il y a juste une table store avec 2 colonnes: key et value.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| etherpad-lite      |
| information_schema |
+--------------------+
2 rows in set (0.01 sec)

mysql> show tables;
+-------------------------+
| Tables_in_etherpad-lite |
+-------------------------+
| store                   |
+-------------------------+
1 row in set (0.00 sec)

mysql> describe store;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| key   | varchar(100) | NO   | PRI | NULL    |       |
| value | longtext     | NO   |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.07 sec)

Les clés concernant les pads commencent par pad:. Vous pouvez avoir un aperçu avec

snippet.sql
SELECT s.key FROM store s WHERE s.key LIKE "pad:%" LIMIT 20;

Le % désigne n’importe quelle suite de caractères. N’utilisez pas plusieurs % dans une même requête ! Cela serait à l’origine d’un nombre astronomique de possibilités, vu la taille de la BDD Etherpad, et donc un temps de calcul astronomique lui aussi.

Pour un pad nommé monpad, il y a normalement:

  • une clé pad:monpad
  • une ou plusieurs clés pad:monpad:revs:ii est compris entre 0 et le nombre de révisions

pad:monpad contient la dernière version

Si le pad vient d’être crée, il y a juste pad:monpad et pad:monpad:revs:0

J’ai crée un nouveau pad sur l’instance de test, nommé newpad, puis j’ai ajouté le texte de test (Ctrl-V) juste après Bienvenue sur Picapad. Ceci a généré la révision suivante (et mis à jour pad:newpad)

mysql> select s.value from store s where s.key="pad:newpad:revs:1";
value
{"changeset":"Z:18h>8=l*0+8$ de test","meta":{"author":"a.jkPhNoJhljvlAjjq","timestamp":1585588719641}}

Mais qu’est ce signifie Z:18h>8=l*0+8$ de test ?

Documentation officielle: Changeset Library

Pour comprendre que contient cette mystérieuse chaine de caractères, on va sur pad.test.picasoft.net et on ouvre une console web.

La chaine Z:18h>8=l*0+8$ de test signifie donc quelque chose comme

Pour passer de la révision 0 à la révision 1, on agrandit le document de 1601 à 1609 caractères. On se place au début. On parcours 21 caractères qui restent inchangés. Puis on ajoute les 8 caractères suivants: " de test"

Ces tests pourraient aider à comprendre pourquoi des pads en production ne fonctionnent pas

Sur l’instance de test, on crée un pad nommé newpad2, puis on fait quelques modifications. Depuis la console mysql, on devrait avoir quelque chose comme:

snippet.sql
mysql> SELECT s.key FROM store s WHERE s.key LIKE "pad:newpad2%" LIMIT 15;
pad2readonly:newpad2
pad:newpad2
pad:newpad2:revs:0
pad:newpad2:revs:1
pad:newpad2:revs:2

On vérifie que tout fonctionne bien, puis on efface la révision 1:

snippet.sql
DELETE FROM store s WHERE s.key="pad:newpad2:revs:1";

On retourne sur le pad. Résultat: tout fonctionne toujours bien. On éteint puis on lance à nouveau etherpad_app. Résultat: le pad s’affiche toujours correctement, mais l’historique ne fonctionne plus

Sur l’instance de test, on crée un pad nommé newpad3, puis on fait quelques modifications. On affiche le contenu de pad:newpad3:

snippet.sql
mysql> SELECT s.value FROM store s WHERE s.key="pad:newpad3";
{"atext":{"text":"Bienvenue sur Picapad de test,          ...          "savedRevisions":[]}

On va mettre à jour la valeur de cette clé avec du JSON invalide. Pour cela, on copie-colle le retour de la commande précédente sur un éditeur de texte, on remplace les ' par \' puis on efface la première {.

On met à jour le champ:

snippet.sql
mysql> UPDATE store SET VALUE='<nouvelle_valeur>' WHERE store.key='pad:newpad3';

On redémarre etherpad-app. Résultat: le pad semble prendre du temps à charger, mais après quelques minutes, on tombe sur un Bad Gateway.

Si on regarde les logs récents (docker logs --since="5m" etherpad-app), on retrouve une erreur du type

[2020-03-30 23:11:31.773] [ERROR] console - JSON-PROBLEM:

Le script nécessaire est préparé par le conteneur db-backup (plus d'infos). Il suffit de l’exécuter:

snippet.bash
amaldona@pica02:/DATA/BACKUP/etherpad$ docker exec -it db-backup bash
root@08cbba05d797:/# ./etherpad-backup.sh

2020-03-23: Les backups de la BDD Etherpad cessent de fonctionner 2020-03-30: On s’en rend compte suite à l'incident. Le dump de la BDD échoue:

root@08cbba05d797:/# ./etherpad-backup.sh
=> etherpad: Backup started: 2020.03.30.140224.sql
mysqldump: Error 1194: Table 'store' is marked as crashed and should be repaired when dumping table `store` at row: 8147475
etherpad: Backup failed

On a réparé la table avec:

snippet.sql
REPAIR TABLE store;

https://dev.mysql.com/doc/refman/8.0/en/repair-table.html

  • technique/adminserv/etherpad/mysql.txt
  • de ppom