Table des matières de l'article :
Lorsqu'il y a des problèmes de performances MySQL, la première solution que nous entendons est celle de séparer l'application ou la partie frontale de la base de données du serveur MySQL. Cette approche est certes académiquement et théoriquement correcte et appréciable, cependant, comme dans de nombreux autres domaines, la théorie ne coïncide pas toujours avec la pratique et dans la tentative de faire bien ou mieux, on se retrouve avec un désastre.
Comprendre les avantages d'avoir un serveur MySQL local plutôt que distant vous aide à réfléchir consciemment à ce qu'il faut faire et à quels pièges et légendes urbains vous devez faire attention.
Même dans les cas où le serveur MySQL et l'application sont sur la même machine, il faut faire attention et avoir un œil sur la manière dont la connexion va s'établir, que ce soit via un socket par exemple, ou via une connexion TCP/IP sur le port 3306 .
Qu'est-ce qu'un socket Unix ?
Un douille, en informatique, désigne une abstraction logicielle conçue pour utiliser des API standard et partagées pour transmettre et recevoir des données sur un réseau ou comme mécanisme de IPC. C'est le point où le code d'application d'un processus accède au canal de communication au moyen d'une porte, obtenant une communication entre des processus travaillant sur deux machines physiquement séparées. Du point de vue d'un programmeur, une socket est un objet particulier sur lequel lire et écrire les données à transmettre ou à recevoir.
Familles de douilles
Les types de protocoles utilisé depuis douille, ils définissent la famille (ou domaine). On peut distinguer, par exemple, deux familles importantes :
- OF_INET: communication entre hôtes distants, via Internet ;
- AF_UNIX: communication entre processus locaux, sur machines Unix. Cette famille est aussi appelée Socket de domaine Unix.
Socket de domaine Unix
Un socket de domaine local o prise locale, en informatique, nous entendons une extrémité d'un canal communication interprocessus similaire à une connexion réseau, mais basée sur le partage de données dans le système de fichiers. Étant donné que ce canal de communication n'est pas implémenté sur les protocoles réseau, il ne peut être utilisé que pour la communication entre processus résidant sur le même hôte. Les sockets locaux de ce type se trouvent dans les systèmes d'exploitation POSIX et Unix, et sont connus dans chacun de ces contextes avec des noms spécifiques, tels que Socket de domaine Unix (Socket de domaine Unix) O Socket IPC local POSIX (Socket IPC local POSIX).
Prise IP ou TCP
Prises IP (en particulier les sockets TCP/IP) sont un mécanisme qui permet la communication entre processus sur le réseau. Dans certains cas, les sockets TCP/IP peuvent être utilisés pour communiquer avec des processus s'exécutant sur le même ordinateur (en utilisant l'interface de bouclage), c'est-à-dire la fameuse adresse 127.0.0.1
Les principales différences entre les familles Unix Domain et TCP Socket
Les sockets de domaine UNIX savent qu'ils s'exécutent et communiquent sur le même système, ils peuvent donc éviter certaines vérifications et opérations (telles que le routage); ce qui les rend plus rapides et plus légers que les sockets IP.
De plus, les sockets de domaine UNIX sont soumis aux autorisations du système de fichiers, tandis que les sockets TCP ne peuvent être contrôlés qu'au niveau du filtre de paquets.
Ainsi, si vous envisagez de communiquer avec des processus sur le même hôte, l'utilisation des sockets Unix est sans doute une meilleure option que les sockets IP.
Lorsque vous vous connectez à une instance MySQL locale, vous disposez de deux méthodes couramment utilisées : utiliser le protocole TCP/IP pour vous connecter à l'adresse locale - "localhost" ou 127.0.0.1 - ou utiliser Socket de domaine Unix .
Si vous avez le choix (si votre application prend en charge les deux méthodes), utilisez Unix Domain Socket car il est à la fois plus sûr et plus efficace.
Comme plus efficace quand même ? Je n'ai pas examiné cela depuis des années, alors voyons comment une version moderne de MySQL fonctionne sur du matériel relativement moderne et sur Linux moderne.
Objectif de l'épreuve
Déterminez s'il existe une différence significative entre l'utilisation d'une connexion TCP locale et d'une connexion socket locale à MySQL.
Ce que nous allons tester
- MySQL 8.0 (serveur Percona 8.0.22-13)
Les tests suivants seront effectués :
- local sur la prise
/var/run/mysqld/mysqld.sock
- local avec connexion TCP
- TCP distant
- fausse prise déportée avec
socat
En ce qui concerne la Socat proxy forwarding nous en avons déjà parlé dans le guide.
Le test lui-même sera effectué avec sysbench.
#!/usr/bin/env bash
sysbench \ /usr/share/sysbench/oltp_read_only.lua \ --threads="2" \ --tables=10 \ --table-size=1000000 \ --report-interval=5 \ --rand-type=pareto \ --forced-shutdown=1 \ --time=300 \ --events=0 \ --point-selects=25 \ --range_size=5 \ --skip_trx=on \ --percentile=95 \ --mysql-host=mysql.to.test \ --mysql-port=3306 \ --mysql-user=bench \ --mysql-password=our-fancy-bench-password \ --mysql-db=bench \ --mysql-storage-engine=INNODB \ run
Nous ne fonctionnerons qu'avec 2 threads, nous comparons donc toujours les mêmes informations.
Nous examinerons les transactions / requêtes par seconde et quelle est la latence au 95e centile pour les connexions utilisées.
utilisation de socat
Sur la machine du serveur MySQL, nous désactivons le réseau sur le serveur MySQL.
Nous allons commenter les paramètres d'écoute TCP et ajouter skip-networking
dans le nôtre [mysqld]
section de la configuration.
#port = 3306
#bind-address = 0.0.0.0
skip-networking
Sur la machine serveur MySQL, nous exécuterons socat pour exposer notre socket sur le port 3306.
socat TCP-LISTEN:3306,reuseaddr,fork \ UNIX-CONNECT:/var/run/mysqld/mysqld.sock
Sur la machine distante, nous utiliserons également socat pour pouvoir faire semblant de nous connecter au socket de la machine locale.
socat UNIX-LISTEN:/var/run/mysqld/mysqld.sock,\ fork,reuseaddr,unlink-early,\ user=mysql,group=mysql,mode=777 \ TCP:mysql.to.test:3306
Note : le retour à la ligne de la chaîne séparée par des virgules ne doit pas avoir d'espace !
De cette façon, nous pouvons faire semblant de nous connecter au socket localhost. Nous verrons comment il fonctionne.
local vs distant
Nous comparons les résultats locaux et distants. Nous utiliserons la connexion socket locale comme référence et comparerons le reste avec cela.
Résultats du socket local :
SQL statistics:
queries performed:
read: 10084576
write: 0
other: 0
total: 10084576
transactions: 347744 (1159.13 per sec.)
queries: 10084576 (33614.79 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 300.0029s
total number of events: 347744
Latency (ms):
min: 1.04
avg: 1.72
max: 20.57
95th percentile: 2.18
sum: 599516.93
Threads fairness:
events (avg/stddev): 173872.0000/208.00
execution time (avg/stddev): 299.7585/0.00
Résultats TCP locaux :
SQL statistics:
queries performed:
read: 7832697
write: 0
other: 0
total: 7832697
transactions: 270093 (900.29 per sec.)
queries: 7832697 (26108.54 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 300.0039s
total number of events: 270093
Latency (ms):
min: 1.36
avg: 2.22
max: 20.91
95th percentile: 2.81
sum: 599599.56
Threads fairness:
events (avg/stddev): 135046.5000/33.50
execution time (avg/stddev): 299.7998/0.00
Résultats TCP distants :
SQL statistics:
queries performed:
read: 2839042
write: 0
other: 0
total: 2839042
transactions: 97898 (326.32 per sec.)
queries: 2839042 (9463.20 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 300.0074s
total number of events: 97898
Latency (ms):
min: 3.33
avg: 6.13
max: 225.58
95th percentile: 7.84
sum: 599783.11
Threads fairness:
events (avg/stddev): 48949.0000/446.00
execution time (avg/stddev): 299.8916/0.00
Résultats de la prise distante :
SQL statistics:
queries performed:
read: 2255707
write: 0
other: 0
total: 2255707
transactions: 77783 (259.16 per sec.)
queries: 2255707 (7515.59 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
General statistics:
total time: 300.1356s
total number of events: 77783
Latency (ms):
min: 4.43
avg: 7.71
max: 241.09
95th percentile: 9.73
sum: 599962.48
Threads fairness:
events (avg/stddev): 38891.5000/228.50
execution time (avg/stddev): 299.9812/0.07
Conclusions sur les performances
genre | transactions/s | requête/s | 95 % de latence (ms) | pourcentage |
---|---|---|---|---|
Prise locale | 1159.13 | 33614.79 | 2.18 | 100% |
TCP local | 900.29 | 26108.54 | 2.81 | 77,7% |
TCP distant | 326.32 | 9463.20 | 7.84 | 28,2% |
"Prise" à distance | 259.16 | 7515.59 | 9.73 | 22,4% |
Lorsque nous avons regardé les graphiques pour la première fois, nous nous sommes immédiatement sentis comme "ok, le TCP local est raisonnablement correct".
Mais si nous examinons les chiffres plus en détail, nous voyons que nous avons un débit supplémentaire de 20 % si nous nous connectons à une prise locale.
Encore une fois, une fois que nous introduisons une connexion TCP sur le câble, le débit chute considérablement.
Étant donné que les sockets de domaine Unix sont beaucoup plus simples et optimisés pour la communication des processus locaux, on pourrait s'attendre à ce qu'ils fonctionnent mieux que TCP / IP sur l'interface de bouclage. En fait, ils fonctionnent beaucoup mieux! Donc, si vous avez le choix, utilisez Unix Domain Sockets pour vous connecter à votre système MySQL local.et vous voulez vraiment un débit maximal de votre base de données MySQL.