Archives de catégorie : Mysql

[MySql] : sauvegarder les bases une à une individuellement

Sauvegarder ses bases de données est essentiel en cas de crash mais aussi pour être en mesure de fournir à tout moment un dump. N’oubliez pas que vous pouvez retrouver les autres articles databases sur cette page.

Par contre il existe de nombreuses manière de faire. Mysql fait cela très bien et très facilement. Mais parfois on a des besoins particuliers.

Par exemple, comme les restaurations portent souvent sur une seule base, on ne souhaite pas disposer d’un dump complet. D’ailleurs cela peut aussi éviter de se trimbaler des fichiers trop gros ou encore de gérer la confidentialité de données entre clients.

Comment sauvegarder les bases mysql une à une c’est à dire en ayant un fichier par base ?

C’est assez simple avec une petite boucle :

for db in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $db | gzip > "/backups/mysqldump-$(hostname)-$db-$(date +%Y-%m-%d-%H.%M.%S).gz"; done

Donc :

  • on dresse la liste des bases avec un show databases
  • on parcourt tout cela avec un for
  • pour chaque base on lance un mysqldump
  • puis on gzippe chaque fichier généré

[Mysql] : comment générer le sql pour recréer un table ?

C’est un article similaire à celui que j’ai déjà pu faire pour oracle mais vous allez vous rendre compte qu’avec mysql c’est plus simple. Eh oui pas de dbms et autres trucs tordus de ce genre un simple « show » suffit.

Ah oui, j’allais oublier qu’avant de faire  ce genre de manip par un « show » je passais par des manips sur les dumps… autant dire que ce n’était pas léger et que cela a des limites très vite atteintes.

Alors comment récupérer le sql d’une table avec la commande « show » ? Facile

mysql> show create table matable;
+---------+-------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+---------+-------------------------------------------------------------------------------------------------------------------------------------+
| matable | CREATE TABLE `matable` (
`id` int(11) DEFAULT NULL,
`monchamp` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+---------+-------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

C’est facile donc et très efficace. Et vous comment pratiquez vous mysql et quelle version ?

mysql-recreate-table

[Mysql] : comment merger deux tables en une ?

Merger des tables sur mysql c’est possible. En effet, vous pouvez faire des associations de table assez facilement. Personnellement je ne suis pas un fan de cette solution nous allons voir pourquoi un peu plus loin. Commençons par créer deux tables similaires au niveau de la structure :

mysql> create table tab3 (f1 varchar(255)) ENGINE=MyISAM;
Query OK, 0 rows affected (0,08 sec)

mysql> create table tab4 (f2 varchar(255)) ENGINE=MyISAM;
Query OK, 0 rows affected (0,08 sec)

Puis insérons des données dans ces tables :

mysql> insert into tab4 values ('table 2');
Query OK, 1 row affected (0,00 sec)

mysql> insert into tab4 values ('table 2');
Query OK, 1 row affected (0,00 sec)

Maintenant créons la table de merge :

mysql> create table fusion (f1 varchar(255)) ENGINE=MERGE UNION=(tab3,tab4) INSERT_METHOD=LAST;
Query OK, 0 rows affected (0,07 sec)

Et voici maintenant son contenu :

mysql> select * from fusion;
+---------+
| f1 |
+---------+
| table 1 |
| table 1 |
| table 2 |
| table 2 |
+---------+
4 rows in set (0,01 sec)

Mais supprimons une des tables composant la table de merge et procédons à un nouveau SELECT :

mysql> drop table tab3;
Query OK, 0 rows affected (0,00 sec)

mysql> select * from fusion;
ERROR 1168 (HY000): Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist

Et voilà mysql nous jette car nous venons de casser un des éléments constitutif de la table de merge. Pas terrible. Vous comprenez donc pourquoi il vaut mieux éviter de créer des tables de merge.

Et vous utilisez vous des tables de ce type ? avez vous rencontré des problèmes avec ?

mysql_table_merge

[Mysql] : comment déconnecter un utilisateur ? (de force)

Mysql est un moteur de bdd performant et sympathique à l’utilisation, un peu à l’image de postgres. Si vous utilisez un WAMP ou LAMP pour faire vos développements, vous utilisez donc Mysql. C’est d’ailleurs certainement ce qui a permis la très forte progression de ce moteur ces dernières années.

Retrouvez d’autres articles sur la page databases.

Un DBA lorsqu’il doit intervenir sur une base ou un moteur, doit parfois être le seul connecter à la base ou à la machine. Mais certaines applications ne rendent pas la main très facilement. C’est souvent moins le cas des utilisateurs humains mais cela peut aussi être le cas d’une personne réticente ou encore mieux le DBA a besoin d’y aller comme un gros bourin et décide de reprendre la main de force.

Bref c’est dans ces derniers cas que l’on peut s’intéresser à vouloir déconnecter un user par la force (en lui coupant son processus).

Comment fait-on ?

La première chose à faire c’est de lister les processus en cours et les users et bases correspondants.

Voici la commande :

mysql> show processlist;

le résultat prend la forme suivante :

 +-----+------+-----------+---------+---------+-------+-------+------------------+
    | Id  | User | Host      | db      | Command | Time  | State | Info             |
    +-----+------+-----------+---------+---------+-------+-------+------------------+
    | 235 | appli1 | 192.20.1.2 | mydb | Query   | 28619 |       | NULL             |
    | 238 | owner | localhost | mydb | Query   |   853 |       | NULL             |
    | 241 | owner | localhost | NULL    | Query   |     0 | NULL  | show processlist |
    +-----+------+-----------+---------+---------+-------+-------+------------------+
    3 rows in set (0.00 sec)

Dans notre cas nous voulons déconnecter appli1. Pour cela il suffit de repérer l’Id de la session (soit 235). Puis lancer :

mysql> kill 235

Et voilà le user appli1 est déconnecté.

N’hésitez pas en commentaire à partager vos pratiques sur mysql.

MySQL.svg

[SQL] : créez des constantes et des noms de résultats

DBA et développeur, cet article est pour vous… y’en faut pour tous les goûts comme on dit. Voici deux outils peu utilisés dans les bases de données que j’ai pu voir récemment. Et pourtant, ils permettent de simplifier votre script sql et de le rendre plus lisible et plus structuré (génial lol).

Les constantes en SQL

Ce n’est pas révolutionnaire mais si vous ne le savez pa déjà, vous pouvez définir un groupe de constante en sql avec la clause « WITH … AS ». Cela vous permettra d’utiliser ces données fixes comme des tables pratiquement.

Par exemple si on définit les constantes de temps :

WITH timeconstants AS (
SELECT 60 as seconds,
       60 as minutes,
       24 as hours,
       365 as days,
       7 as week,
       ['Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi','Dimanche'] as daysweek,
),

C’est pas mal mais comment utiliser ces constantes ? comme une requête.

SELECT seconds, minutes, hours, days FROM timeconstants;

Enfantin comme dirait l’autre.

Les noms de résultats

Je parlerai plutôt d’alias mais souvent en sql on parle d’alias pour les alias de table par exemple et on l’utilise plutôt dans la clause FROM. En totu cas le principe est presque el même sauf qu’il s’agit à la manière d’un vue d’attribuer un alias à une requête entière.

On le fait ainsi :

myextract AS (
   SELECT
   IF(colonne1 < 10, "little", "big") AS qualified_sale,
   colonne1,   nb_hours,   colonne2 / 10  FROM mytable)

Et si on combine les deux on retrouve des trucs du genre :

SELECT nb_hours * minutes * secondes AS timer
FROM mytable, timeconstants;

Alors je fais un peu n’importe quoi mais c’est un exemple.Ici on utilise les constantes minutes et secondes pour calculer les heures passées en secondes.

L’intérêt vous le voyez c’est que désormais tout possède un nom et que pour appeler les éléments ils doivent être définis à travers le « FROM ». Derrière il est beaucoup plus simple de faire de la modélisation et surtout si vos constantes évoluent vous n’avez pas besoin de revoir toutes vos requêtes.

 

Pour ces éléments SQL que nous venons de voir, on parle de CTE dans le jargon DBA. CTE pour Common Table Expression. Ces petites clauses permettent de jouer sur les « alias » pour créer des pseudos tables qui ne sont pas non plus des vues et qui visent à simplifier le travail de maintenance.

[Python] : comment requêter une base mysql avec mysql.connector ?

Mysql Connector est le module le plus répandu pour utiliser une base de données mysql à partir de python. Il est relativement facile à utiliser. Nous aurons l’occasion de voir dans d’autres articles des manipulations plus complexes mais il faut bien commencer par… le commencement.

Comment réaliser un simple SELECT et afficher son résultat en Python ? voici comment faire si vous êtes débutant.

import mysql.connector

madatabase = mysql.connector.connect(
  host="localhost",
  user="nom_utilisateur",
  passwd="mon_password",
  database="mabase"
)

session = madatabase.cursor()
sql = "SELECT * FROM matable;"
session.execute(sql)

resultat = session.fetchall()

for x in resultat:
  print(x)

session.close()


Donc quelles commandes avons nous passé ?

  • import du module
  • création d’une instance madatabase avec les paramètres de connexion. C’est tout à fait classique on retrouve cela avec de nombreux modules de moteurs de bases de données
  • ouverture d’une connexionavec l’instanciation de la classe cursor
  • la variable sql contient la requête à passer
  • on lance la requête avec notre variable
  • on récupère tous les résultats (sous forme de liste)
  • il ne reste plus qu’à parcourir la liste
  • et on oublie pas de dire au revoir et merci au serveur en fermant la session

Vous pouvez d’ores et déjà retrouver plus d’infos en ligne sur le site mysql et sa rubrique dédiée à ce module Python.

[Mysql] :Comment diagnostiquer et optimiser votre base et moteur ? avec mysqltuner

Mysql est une base que l’on trouve souvent derrière de nombreux outils web (par exemple wordpress…). Elle s’est généralisée avec la montée en puissance de WAMP ou LAMP. Mais souvent les moteurs et les bases installés sont installés avec des valeurs par défaut sans optimisation. C’est pourquoi, de temps en temps, il est nécessaire de faire des optimisations (défragmentation de base…).

Dans ce genre de travail d’optimisation de bases, on cherche des outils qui permettront de faire une partie du travail à notre place. Et c’est là que vous trouverez votre bonheur avec le binaire intitulé mysqltuner.

Il est facile à installer et comme vous le verez ci-dessous son rapport est plutôt bien fichu. tout cela en perl donc on aime bien.

Pour l’installer rien de plus simple :

sudo apt-get install mysqltuner

Et après on le lance simplement :

└─ $ ▶ mysqltuner

 >>  MySQLTuner 1.3.0 - Major Hayden <major@mhtx.net>
 >>  Bug reports, feature requests, and downloads at http://mysqltuner.com/
 >>  Run with '--help' for additional options and output filtering
Please enter your MySQL administrative login: ------
Please enter your MySQL administrative password: 
[OK] Currently running supported MySQL version 5.5.60-0+deb8u1
[OK] Operating on 64-bit architecture

-------- Storage Engine Statistics -------------------------------------------
[--] Status: +ARCHIVE +BLACKHOLE +CSV -FEDERATED +InnoDB +MRG_MYISAM 
[--] Data in MyISAM tables: 714M (Tables: 400)
[--] Data in PERFORMANCE_SCHEMA tables: 0B (Tables: 17)
[--] Data in MEMORY tables: 496K (Tables: 4)
[--] Data in InnoDB tables: 55M (Tables: 14)
[!!] Total fragmented tables: 28

-------- Security Recommendations  -------------------------------------------
[!!] User 'rundeck@%' has no password set.

-------- Performance Metrics -------------------------------------------------
[--] Up for: 18d 0h 10m 24s (136M q [87.417 qps], 261K conn, TX: 113B, RX: 23B)
[--] Reads / Writes: 80% / 20%
[--] Total buffers: 192.0M global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 597.8M (15% of installed RAM)
[OK] Slow queries: 0% (81/136M)
[OK] Highest usage of available connections: 19% (29/151)
[OK] Key buffer size / total MyISAM indexes: 16.0M/266.3M
[OK] Key buffer hit rate: 99.5% (362M cached / 1M reads)
[OK] Query cache efficiency: 94.4% (123M cached / 131M selects)
[!!] Query cache prunes per day: 258354
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 508K sorts)
[!!] Temporary tables created on disk: 35% (1M on disk / 3M total)
[OK] Thread cache hit rate: 99% (1K created / 261K connections)
[!!] Table cache hit rate: 0% (400 open / 393K opened)
[OK] Open file limit used: 73% (756/1K)
[OK] Table locks acquired immediately: 99% (9M immediate / 9M locks)
[OK] InnoDB buffer pool / data size: 128.0M/55.5M
[OK] InnoDB log waits: 0
-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Enable the slow query log to troubleshoot bad queries
    When making adjustments, make tmp_table_size/max_heap_table_size equal
    Reduce your SELECT DISTINCT queries without LIMIT clauses
    Increase table_open_cache gradually to avoid file descriptor limits
    Read this before increasing table_open_cache over 64: http://bit.ly/1mi7c4C
Variables to adjust:
    query_cache_size (> 16M)
    tmp_table_size (> 16M)
    max_heap_table_size (> 16M)
    table_open_cache (> 400)

Vous avez donc une liste de recommandations qui vous permettront d’atteindre votre but pour optimiser votre moteur et votre base :

  • faire un OPTIMIZE TABLE
  • activé le slow query
  • ajuster des variables de configuration  : tmp_table_size…
  • réduire les volume de « SELECT DISTINCT » en utilisant la clause « LIMIT »

Les choses sont donc relativement bien formulées. Je pense que nous aurons l’occasion de revenir en détail sur certaines de ces actions et de leurs effets.

De votre côté utilisez vous ce genre d’outils ?

[Php] : mysql passage à mysqli avec php7

La petite surprise du passage en Debian Stretch. Bien sûr que vous passez à php7 mais celui-ci ne propose plus la librairie mysql qui devient (en gros) mysqli. Du coup, il faut se replonger dans les vieux trucs qui tournaient depuis plusieurs années et c’est pas plaisant. C’est même moche parfois.

Alors pour ceux qui sont un peu fou dans leur tête, vous pouvez faire cohabiter plusieurs versions de php mais je vous laisse regarder cet article c’est pas fun. Mais bon c’est surtout pas une bonne idée il faut monter en version php7 c’est ainsi.

Alors il faut retrousser ses manches et se mettre à convertir. Mysqli est procédurale contrairement à mysql. Donc cela peut impacter un peu plus votre code. Dans les faits c’est pas la mer à boire si vous voulez vous le faire en odschool.

Si vous deviez en retenir une chose c’est que désormais les fonction intègre systématiquement une variable supplémentaire la connexion. Auparavant vous faisiez la connexion au début de votre page et ensuite vous n’aviez plus à en parler mysql_query($sql). Désormais il faut rappeler la variable de la cconnexion : mysqli_query($connexion,$sql).

Pour la connexion cela reste simple :

mysqli_connect($server, $user, $password, $db);

Dnas mon cas pour les datatables de Alan Jardine :

$connexion = mysqli_connect($gaSql['server'],$gaSql['user'],$gaSql['password'],$gaSql['db']);

 

[Mysql] [Mariadb] : réinitialiser le mot de passe root (faut pas le dire)

Les DBA ne sont pas des personnes parfaites, au même titre que d’autres. Cela arrive de perdre un mot de passe et même si le mot de passe est celui du user root. Bon c’est quand même bien embêtant je l’avoue, ça fait pas très pro.

Réinitialiser le mot de passe est souvent la seule solution. Voici une des solutions possible :

sudo /etc/init.d/mysql stop

sudo mysqld_safe --skip-grant-tables &

mysql> use mysql;

mysql> update user set authentication_string=password('monnouveaumotdepasse') where user='root';
hacker screen

Photo by Markus Spiske freeforcommercialuse.net on Pexels.com

Une autre solution en passant par systemd :

# on relance mysql sans les GRANTS sur les tables
systemctl set-environment MYSQLD_OPTS="--skip-grant-tables"
systemctl restart mysql

# puis on set le nouveau mot de passe
UPDATE mysql.user SET password=PASSWORD('monouveaumotdepasse') WHERE User='root' AND Host = 'localhost';
FLUSH PRIVILEGES;

#et surtout sinon tu es mort tu remets les permissions en place merci !
systemctl unset-environment MYSQLD_OPTS
systemctl restart mysql

 

[MySql] : vider toutes les tables d’une base

On a pas tous une âme de DBA mais ces dernières années les sgbd ce sont tellement simplifiés que finalement les actions restent assez accessibles pour tous. Alors on cherche toujours à aller un peu plus loin.

Mysql est très facile à utiliser en ligne de commande. Du coup cela permet aussi de manipuler ses output dans une ligne bash ou awk.

Vider toutes les tables d’une base de données en une ligne c’est possible voici comment :

MYSQL_CONNECT="mysql -h hostname -u username -ppassword -D database";
$MYSQL_CONNECT -Bne "show tables;" | awk '{print "set foreign_key_checks=0; drop table `" $1 "`;"}' | $MYSQL_CONNECT unset MYSQL 

Donc :

  • on créé une variable permettant de lancer le binaire mysql avec les éléments de connexions
  • on lance le binaire avec l’option -Bne ( n : flush du cache , B : tabulation comme séparateur , e : sql entre quotes )
  • on génère le sql pour dropper la table mais on set le fait de ne pas s’occuper des clés étrangères
  • on unset les variables
person hands on assorted color plastic lid lot

Photo by Krizjohn Rosales on Pexels.com

 

[Mysql] [Docker] : Sauvegarde mysql pour conteneurs Docker

Je publie ce code car je le trouve bien pratique. Le raisonnement me semble logique et j’ai apprécié le rédiger alors cela peut surement vous inspirer. Si vous êtes curieux, vous pouvez retrouver mes commandes docker sur cette page.

Alors je vous dresse les points essentiels du code car le mien fait intègre aussi postgres et mariadb (identique à mysql exactement).

Premièrement on liste les ID, les noms et les images des conteneurs. Comme on log tout cela cela permet de recréer aussi très rapidement un conteneur Docker identique. Et puis cela permet aussi de tester le dump facilement.

docker ps --format "{{ .ID }}|\
{{ .Names }}|\
{{.Image}}" |\
while IFS="|" read var1 var2 var3;\
do

Ensuite on nettoie le nom du conteneur car Docker ajoute un sha pour le rendre unique et c’est pas très causant. et on peut se créer un répertoire local de backup (mais cela peut aussi être un point de montage.

var2=$(echo $var2 | sed -e 's/\(.*\)\..*$//g')
BACKUP_DIR="/dir_export/"
DUMP_DIR=${BACKUP_DIR}${var2}/
DUMP=BACKUP_DIR="/export/sgbd-dumps/"
DATEDUMP=$(date +%Y-%m-%d)
DUMP=${DATEDUMP}.${var2}

et on commence par logger quelques infos :

echo "---- ${DATEDUMP} /  Dump du container ${var2}    -----" > ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-name >>"$var2 >> ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-image >>"$var3 >> ${DUMP_DIR}${DUMP}.log
 echo ${DATEDUMP}"-dump >>"${DUMP_DIR} >> ${DUMP_DIR}${DUMP}.log

Et c’est parti on lance la sauvegarde mysqldump en lancant un docker exec sur l’ID du conteneur recueilli.

echo ""
echo "---- ${DATEDUMP} /  Dump du container ${var2}    -----"
docker exec ${var1} mysqldump -u  --password= --all-databases  > ${DUMP_DIR}${DUMP}.sql

Alors on aurait pu ajouter un gzip directement dessus et ne sauvegarder qu’une seule base. Personnellement on ne sait on part sur un truc complet. Et pui savant de gzippé on vérifie le boulot 😉

Alors comment on fait pour tester notre dump ???

C’est simple. On créé un conteneur identique et ensuite on importe notre dump dedans. N’ayez pas peur c’est hyper facile.

docker run --name testsgbd -e MYSQL_ROOT_PASSWORD= -tid $var3 | grep -vi warning
sleep 40

On voit que $var3 nous permet de lancer la même image que dans le conteneur sauvegardé. Et on met tout cela en pause durant 40 secondes. C’est beaucoup mais on s’assure que le conteneur est bien lancé (ou au moins à eu le temps).

Et la on importe mais pas n’importe comment. On fait un test (un if) sur la commande d’import mysql lancée à travers docker. Si aucun message d’erreur on à ainsi un dump conforme sinon KO. Et si OK on gzip

if [ -n "$(docker exec -i testsgbd mysql -uroot -ppassRoot <${DUMP_DIR}${DUMP}.sql 2>&1 | grep -vi Warning )" ];then
                       echo " >>> ${DATEDUMP} : [Error]" >> ${DUMP_DIR}${DUMP}.log
                      echo "[Pb import]"
                        rm -f ${DUMP_DIR}${DUMP}
                else
                        echo " >>> ${DATEDUMP} : [OK]" >> ${DUMP_DIR}${DUMP}.log
                        echo "[Import OK]"
                        echo "Gzip..."
                        gzip ${DUMP_DIR}${DUMP}*.sql
                        echo "fin"
                fi

et surtout on oublie pas de nettoyer en supprimant l’image créée.

docker rm -f testsgbd

Alors c’est pas simple tout cela ?

Je trouve que si et que ça mérite d’être partagé, c’est pour cela que cela valait bien un article.