Comparatif MySQL dans le PaaS, épisode 1 : Google Cloud SQL

mercredi, décembre 5, 2018
By David Baffaleuf in Google Cloud Platform (dbaffaleuf@capdata-osmozium.com) [73 article(s)]

Je vous propose de découvrir ensemble de quelle manière MySQL est implémenté dans le PaaS, chez les 3 principaux fournisseurs de ce type de service : Google, Microsoft et Amazon, au rythme d’un épisode par plateforme.

Dans chaque épisode nous passerons en revue les différentes caractéristiques techniques de l’offre, nous verrons les différences avec une distribution classique en termes de fonctionnalités, tout ça avec notre oeil de DBA, en insistant sur la maintenabilité et le diagnostic avant tout. Parce que ne vous y trompez pas, vous aurez toujours des problèmes de performance dans le cloud, et il vous faudra toujours des méthodes et des outils pour pouvoir les analyser.

Egalement nous verrons comment il est possible de migrer des bases on-premise vers l’équivalent cloud, en essayant à chaque fois de minimiser l’indisponibilité lors de la bascule.

Rappels: dans le cas du PaaS (Platform as a Service), la base de données est un service hébergé et accessible à distance, pour laquelle l’infrastructure est managée et donc invisible côté utilisateur. A la différence du IaaS (Infrastructure as a Service), où l’infrastructure est visible et accessible à l’utilisateur ( = machines virtuelles).

Dans cette série, nous ne parlerons que du PaaS. L’intérêt principal du PaaS sur le IaaS est que l’infrastructure est managée: on ne s’occupe plus de gérer des serveurs, des systèmes d’exploitation, des patches, des sauvegardes, etc… On se concentre sur le service.

A noter également que le monde du cloud est un monde qui bouge très vite donc les informations qui sont présentées ici sont susceptibles d’évoluer dans le futur.

Le décor:

Sur GCP, le découpage des briques de service est le suivant :

Compute regroupe l’App Engine (runtimes, exécution serverless), une brique Kubernetes, et le Compute Engine qui héberge le IaaS, les machines virtuelles, donc l’équivalent d’EC2 sur AWS.

Big Data propose une brique base de données basée sur un moteur de stockage et d’interrogation en colonne (BigQuery) et une suite d’outils orientés datawarehouse.

Storage : il faudra aller chercher nos bases de données relationnelles au rayon du stockage au milieu des briques NoSQL (BigTable, DataStore, et récemment MemoryStore) et stockage pur type S3 (Cloud Storage), sous la dénomination Cloud SQL. Derrière ce titre se cache en réalité deux offres : une sur MySQL, une sur PostgreSQL.

Il existe d’autres briques techniques comme la partie réseau/VPC, et StackDriver qui propose des outils de logging, métrologie et diagnostic, que nous verrons un peu plus loin.

Ces briques sont déployables de manière globale sur une ou plusieurs régions chacune comportant au moins 3 zones distinctes proches géographiquement (datacenters). Actuellement il existe 18 régions opérationnelles et 2 régions en cours de déploiement:

Chaque région propose une gamme de plateformes techniques pour l’exécution des services : types et nombre de CPU, etc…

Dans l’exemple de la région europe-west4 (Pays-Bas), nous avons trois zones -a, -b et -c, dans lesquelles nous pouvons déployer des tiers jusqu’à 96vCPUs Skylake ou Broadwell, nous pouvons utiliser l’option Local SSD (SSD en attachement direct sur l’hyperviseur, meilleures performances, meilleur prix mais aucune redondance) ainsi que le mode Sole Tenant nodes qui permet de dédier un hyperviseur pour un compte. Pour plus de détails, je vous invite à consulter la doc en ligne de GCP.

Certaines ressources comme les identités, les images, etc… peuvent être globales, alors que d’autres comme des sous réseau, des adresses IP, des instances ou du stockage peuvent être confinés à une région voire une seule zone.

Pour représenter une application globale, il existe la notion de projet: c’est un peu l’espace de nom global du déploiement d’une application. Chaque ressource est unique dans un projet, chaque projet est unique dans GCP. C’est sur la base du projet qu’est établie la facturation.

Enfin, l’accès aux ressources peut se faire de trois manières différentes :

– Via la console web : dans un navigateur, on accède aux différents services, paramétrage, exécution ou arrêt, duplication, sauvegarde, etc… ainsi qu’au monitoring de ces services.

– Via un CLI (Command Line Interface) : tout ce qui se fait dans la console retrouve un équivalent dans la commande gcloud. Il suffit de l’installer sur un linux ou windows client et de piloter le projet à partir de la ligne de commande:

$ gcloud sql instances list
NAME             DATABASE_VERSION  LOCATION        TIER              PRIMARY_ADDRESS  PRIVATE_ADDRESS  STATUS
mysql56-src      MYSQL_5_6         europe-west4                      -                -
mysql-cap-cloud  MYSQL_5_7         europe-west4-a  db-n1-standard-1  35.204.174.228   -                STOPPED
mysql5-slv       MYSQL_5_6         europe-west4-b  db-n1-standard-1  35.204.147.252   -                FAILED

– Via les API en fonction du langage choisi, il en existe pour tous les goûts : Python, Go, Ruby, PHP, Java, Node.js, C#, etc…

Cloud SQL pour MySQL:

Alors que PostgreSQL est une offre relativement récente (2016) et assez peu mature par rapport à ce que produit Amazon notamment (RDS / Aurora), l’offre MySQL en est à sa deuxième génération, s’est enrichie au fil des années et bénéficie d’un peu plus de recul sur les fonctionnalités. Aujourd’hui il est toujours possible de provisionner des instances MySQL de première génération mais elles sont proposées seulement pour compatibilité et seront retirées probablement dans les mois à venir.

Avant de passer à la pratique, regardons sur le papier les principales caractéristiques techniques d’une instance MySQL gen II:
– Seules les versions 5.6 et 5.7 sont supportées.
– InnoDB est le seul moteur de stockage supporté.
– Pour le choix du tier, 64 vCPUs, 416 Gb de RAM et 10Tb de disque au maximum.
– Concernant le maintien en conditions opérationnelles, les sauvegardes sont automatiques et les restaurations possibles à un point dans le temps, également les patches mineurs sont appliqués en précisant une fenêtre de maintenance de préférence.
– Concernant la disponibilité, les données sont dupliquées sur 2 autres régions idéalement proches géographiquement, le failover d’une zone à l’autre est automatisé avec une VIP.

Les tiers disponibles :

Lors de la création d’une instance Cloud SQL MySQL de génération II, il est possible pour dimensionner la plateforme d’exécution de choisir entre les modèles suivants:
db-f1-micro / db-g1-small : vCPU partagés avec d’autres machines micro / small, 1.6Gb de mémoire et 3Tb de données maximum, 1000 connexions simultanées.
db-n1-standard-1 à -64 : de 1 à 64 vCPUs, de 3 à 240Gb de RAM, 10Tb de stockage et 4000 connexions simultanées.
db-n1-highmem-2 à -64 : de 2 à 64 vCPUs, de 13 à 416Gb de RAM, 10Tb de stockage et 4000 connexions simultanées.

Le stockage disponible :

On peut choisir entre un stockage de type SSD (par défaut) ou magnétique. Pour les SSD, la taille du volume et le nombre de vCPUs vont affecter le nombre d’IOPS et le débit en Mb/s :

Pour un tier à 15 vCPUs ou moins, il faudra provisionner à 500Gb pour obtenir 15000 IOPS et 240Mb/s qui sont les maximums. C’est un travers que l’on va retrouver chez les concurrents : le fait de toujours surprovisionner la capacité des disques pour pouvoir obtenir de meilleures performances. Si pour un besoin de moins de 100Gb on alloue 500Gb parce qu’il nous faut des IOPS et du débit, on ne se préoccupera plus de l’espace disque, d’autant qu’il augmentera tout seul par défaut (sans jamais pouvoir être réduit):

Principal danger de cette philosophie : on risque de perdre de vue la maîtrise de l’espace disque du point de vue des performances : un index fragmenté ne va pas coûter plus cher en stockage, par contre il va coûter plus cher en temps d’exécution, en temps vCPU, en verrous maintenus plus longtemps, etc…

Les coûts

Le coût du stockage (novembre 2018 pour la région europe-west4 – Pays-Bas):
– $0.187/Gb/mois pour les SSD
– $0.099/BG/mois pour les disques magnétiques.

Un exemple de configuration: 1 instance db-n1-standard-16 :
– Fonctionnement en 24/7
– Avec un failover replica
– 16 vCPUs dédiés
– 60Gb de RAM
– 200 Gb de stockage SSD
– 1Tb de stockage pour les sauvegardes

En utilisant la calculette on obtient:

Plus de détails sur les tiers disponibles et sur les coûts : https://cloud.google.com/sql/pricing#2nd-gen-pricing. L’idée est de garder ce chiffre en tête pour pouvoir le comparer ensuite à ce que peut donner un équivalent sur AWS ou Azure dans les articles suivants.

Les limitations par rapport à une distribution classique:

1) Pas de LOAD DATA INFILE dans le PaaS. Ca paraît logique. A noter que sur Cloud Compute, LOAD DATA LOCAL INFILE est lui supporté.

2) Dans la même veine, pas de SELECT … INTO OUTFILE / DUMPFILE.

3) Pas de CREATE FUNCTION … SONAME pour le code externe (.so)

4) Tout ce qui est lié au privilège SUPER : par exemple pas moyen de modifier des paramètres globaux, pas de GRANT ALL, pas de CHANGE MASTER TO, etc…

5) Peut être le plus impactant : dans la mesure où la réplication GTID sert de cadre technique à toute la redondance, les paramètres GTID doivent être activés et donc pas de CREATE TABLE AS SELECT ni de CREATE TEMPORARY TABLE dans les transactions.

6) Attention ! Performance_schema n’est accessible que pour les tiers supérieurs à db-n1-standard-8 ou db-n1-highmem-4.

La connexion

Deux manières de se connecter : soit utiliser un client classique (mysql, SQLYOG, MySQL Workbench), soit utiliser l’outil Cloud SQL Proxy.

Cloud SQL proxy s’installe sur le client et une fois associé au compte et au projet, permet de gérer les connexions de manière plus simple et plus sécurisée:

Passer par le client natif sera généralement un peu plus rapide que passer par le proxy, mais si la connexion doit être portée par SSL il faudra gérer les certificats soit-même:

$ ./cloud_sql_proxy -instances=durable-epoch-220407:europe-west4:mysql-cap-cloud=tcp:3306 &
[1] 10131
2018/12/03 10:39:37 Listening on 127.0.0.1:3306 for durable-epoch-220407:europe-west4:mysql-cap-cloud
2018/12/03 10:39:37 Ready for new connections

$ time mysql --login-path=mygcpsql --execute="select count(1) from sakila.payment;"
+----------+
| count(1) |
+----------+
|    16049 |
+----------+

real	0m0.128s
user	0m0.000s
sys	0m0.004s

$ time mysql --user=root --host=127.0.0.1 --port=3306 --password=****** --execute="select count(1) from sakila.payment;"
Warning: Using a password on the command line interface can be insecure.
2018/12/03 10:32:00 New connection for "durable-epoch-220407:europe-west4:mysql-cap-cloud"
+----------+
| count(1) |
+----------+
|    16049 |
+----------+

real	0m0.162s
user	0m0.004s
sys	0m0.000s
$ 2018/12/03 10:32:00 Client closed local connection on 127.0.0.1:3306


Cela dit, l’outil reste assez vaste et nécessitera un approfondissement via un article dédié. A titre personnel, j’utiliserai plutôt le client natif mysql d’autant que le login-path fonctionne sans problème avec une instance dans le cloud.

La haute disponibilité et les possibilités de réplication:

Nous avons vu plus haut que le failover peut être automatisé. Attention il n’est pas actif par défaut, le plus simple est de provisionner une instance de secours au moment du déploiement de l’instance principale :

A noter qu’il est toujours possible de rajouter une instance de secours plus tard via la console, gcloud ou une API dans le langage de votre choix.

Cette instance de secours sera appelée failover replica. Il ne peut y en avoir qu’une seule par instance master, elle doit se trouver dans une autre zone mais nécessairement dans la même région, et ce sera une exacte copie en termes de configuration. La synchronisation sera assurée par la réplication semi-synchrone MySQL en mode GTID. Ce qui implique que les binlogs seront activés sur le master, donc coût de stockage supplémentaire.

Enfin, ce failover replica fera évidemment l’objet d’une facturation supplémentaire. La mauvaise nouvelle c’est qu’il sera facturé au même prix que l’instance master. A noter que le prix évoqué un peu plus haut inclut déjà le coût du failover replica, mais je trouve dommage de facturer une instance dormante au même prix qu’une instance active.

Pour assurer le failover automatique, outre le failover replica, plusieurs mécanismes sont en place:
– L’écriture d’une ligne de ‘heartbeat’ dans une table système mysql.heartbeat de l’instance master, chaque seconde.
– Une VIP pour permettre de raccrocher les applications sur la nouvelle instance promue principale suite à la bascule.

Un système externe monitore l’arrivée des lignes de heartbeat et si aucune nouvelle ligne n’est lisible au delà de 60 secondes et si le failover replica est disponible, un failover sera initié:

1) On attend que le failover replica ait terminé de rejouer toutes les transactions en attente.
2) La VIP et le nom de l’instance master basculent sur le failover replica qui est promu nouveau master.
3) En arrière plan, un nouveau failover replica est recréé dans une autre zone, c’est la raison pour laquelle il y a au moins 3 zones par région. Si une zone complète est en échec il en reste toujours deux pour assurer la disponibilité.

Au delà de la partie failover, il est aussi possible de créer d’autres slaves en lecture seule, des read replicas. Dans ce cas, il est possible de créer plusieurs read replicas pour un même master, et dans le cas d’un failover ils seront automatiquement recréés également.

Plusieurs choses à noter pour les read replicas :
– Ils seront synchronisés avec le master en utilisant la réplication GTID asynchrone classique.
– Il n’est pas possible de faire des sauvegardes ou recréer d’autres slaves à partir d’un read replica.
– Ils peuvent être externes à GCP, de la même manière un master peut être externe aussi, ce qui va être intéressant dans le cas d’une migration:

Backup & restauration:

Déjà il existe 2 types de backups : les backups automatisés et les backups à la demande. Associés à l’activation des logs binaires, ils fournissent une solution de restauration à un point dans le temps, ce qui est très important vis à vis de votre RPO.

Les backups automatisés seront lancés dans une fenêtre de 4 heures que l’on peut définir à la création de l’instance ou plus tard :

7 backups en ligne seront conservés, dans le marbre, pour un coût du stockage à $0.088/mois/GB (novembre 2018, Région europe-west4).

Il est ensuite possible de lancer des backups à la demande. Ces backups ne suivront pas la politique de rétention des backups automatiques, ils resteront donc sur un bucket disque tant qu’ils ne seront pas supprimés:

$ time gcloud sql backups create --instance=mysql-cap-cloud
Backing up Cloud SQL instance...done.                                                                                                                                                                     
[https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud] backed up.

real	0m34.714s
user	0m0.204s
sys	0m0.144s

La question de la cohérence de ces backups est évacuée par le postulat de n’avoir qu’InnoDB en moteur de stockage pour les génération II, ce qui revient à faire un mysqldump en –single-transaction. Pas besoin de faire un FLUSH TABLE WITH READ LOCK donc, toutefois comme sur les distributions traditionnelles, il vaut mieux éviter de lancer des opérations DDL pendant la sauvegarde.

La liste des backups est consultable traditionnellement via la console, gcloud ou une API:

$ gcloud sql backups list --instance=mysql-cap-cloud --sort-by=WINDOW_START_TIME
ID             WINDOW_START_TIME              ERROR  STATUS
1542664800648  2018-11-19T22:00:00.648+00:00  -      SUCCESSFUL
1543505077704  2018-11-29T15:24:37.704+00:00  -      SUCCESSFUL
1543505836176  2018-11-29T15:37:16.176+00:00  -      SUCCESSFUL

Je n’ai pas trouvé le moyen de voir la taille par backup, dommage car la chaîne est à base de backup complet (le plus ancien) et ensuite de backups incrémentaux, donc on devrait pouvoir voir le gain d’espace disque sur les backups additionnels.

Une restauration peut se faire sur l’instance source mais aussi d’une instance à une autre en précisant –backup-instance et –restore-instance :

$ gcloud sql backups restore 1543505077704 --restore-instance=mysql-cap-cloud --quiet
Restoring Cloud SQL instance...done.                                                                                                                                                                  
Restored [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud].

ou

$ gcloud sql backups restore 1543505077704 --backup-instance=mysql-cap-cloud --restore-instance=mysql-cap-cloud-2 --quiet
Restoring Cloud SQL instance...done.                                                                                                                                                                  
Restored [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud-2].

Le backup source sera identifié par la clé 1543505077704 qui reprend le BACKUP_ID renvoyé par la commande de listing vue plus haut. Pendant la durée de la restauration, toute la cible est évidemment inaccessible:

$ gcloud sql instances describe mysql-cap-cloud | grep '^state'
state: MAINTENANCE

Enfin, si des réplicas failover ou read existent, il faudra les supprimer et les reprovisionner une fois la restauration effectuée.

Au delà de la solution via –backup-instance et –restore-instance, il existera une solution pour cloner une instance existante et en créer une nouvelle :

gcloud sql instances clone mysql-cap-cloud mysql-cap-cloud2

Pour clore le chapitre sur les backups, on peut dire qu’ils ne peuvent être utilisés qu’au sein du même projet. On ne peut pas restaurer vers une instance d’un autre projet, ou sur une instance de première génération, etc…

Arrêt & redémarrage:

Cloud SQL est un service facturé à l’utilisation: lorsque l’instance est coupée, seul le stockage est facturé. Donc si vous n’avez pas besoin d’avoir une instance démarrée en permanence (par exemple vos environnements hors prod), vous allez faire des économies, mais cela implique d’utiliser un mécanisme spécifique pour gérer les arrêt et démarrages.

Tout est contrôlé à partir du paramètre du service ACTIVATION_POLICY. Attention ce n’est pas un paramètre MySQL mais bien un paramètre Cloud SQL.

Globalement ce paramètre peut être positionné soit à :

ALWAYS : le service est démarré et facturé.

$ gcloud sql instances patch mysql-cap-cloud \
	--activation-policy=ALWAYS
Patching Cloud SQL instance...done.                                                                                                                                                                                                          
Updated [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud].

NEVER : le service est stoppé et non facturé.

$ gcloud sql instances patch mysql-cap-cloud \
	--activation-policy=NEVER 
Patching Cloud SQL instance...done.                                                                                                                                                                                                          
Updated [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud].

Pour les instances de génération I, il existe un paramètre ON_DEMAND qui implique que la dernière déconnexion coupe le service et la première connexion le redémarre, mais pour une instance de génération II cette option n’est pas disponible et devrait disparaître à terme.

Il existe évidemment l’équivalent côté console et API mais si vous souhaitez automatiser une mise en sommeil de vos instances de dev / recette par exemple, le plus efficace sera de piloter ACTIVATION_POLICY via un client distant, qui peut être chez vous on-premise ou dans une VM Cloud Compute.

Si un arrêt suivi d’un redémarrage immédiat est souhaité, il existe une troisième solution mais dans ce cas il n’y a pas d’arrêt de la facturation:

$ gcloud sql instances restart mysql-cap-cloud
The instance will shut down and start up again immediately if its 
activation policy is "always." If "on demand," the instance will start
 up again when a new connection request is made.

Do you want to continue (Y/n)?  Y

Restarting Cloud SQL instance...done.                                                                                                                                                                                                        
Restarted [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql-cap-cloud].

A noter que par défaut si vous utilisez mysqladmin shutdown l’instance s’arrête et redémarre immédiatement, ce n’est donc pas une option…

Remarque : La valeur de @@server-id est générée aléatoirement, elle est notamment régénérée à chaque changement de ACTIVATION_POLICY ou redémarrage via gcloud sql instances restart…. Ça surprend un peu au début mais à la réflexion ce n’est pas vraiment un problème dans la mesure où on n’utilisera que la réplication GTID et la valeur de @@server-uuid, elle, ne change jamais.

Fenêtres de maintenance:

A partir de la génération II, on peut choisir sa fenêtre de maintenance, pendant laquelle les mises à jour nécessitant les arrêt / redémarrages de l’instances peuvent survenir:

Les failover replicas suivront la même politique donc il n’est pas possible de basculer pendant cette période. Il y a risque donc de downtime, sans garantie (les dates de mise à jour ne sont pas annoncées à l’avance). C’est donc une partie assez délicate pour 2 raisons principales:

1) Si vous avez à la fois vos environnements hors prod et production dans Cloud SQL, il sera compliqué de pouvoir patcher le hors prod et le laisser tourner suffisamment longtemps pour détecter un problème suite à une mise à jour. Les instances de génération II disposent d’un second paramètre maintenance timing qui permet d’indiquer quelles instances sont patchées en avance et quelle instances sont patchées plus tard, mais cela reste très vague on ne peut pas vraiment déterminer un écart de temps précis entre les instances patchées en Earlier et les instances patchées en Later:

2) Ensuite, il y a bien downtime c’est une infrastructure managée et vous ne pourrez rien y faire. Si votre application nécessite d’être disponible 24/7 sans interruption programmée, il risque d’y avoir un os. Vous n’avez qu’un contrôle marginal sur l’application de ces patches, statistiquement il y a environ 1 à 2 patches par mois, votre instance est coupée environ 5 minutes à chaque fois. On se souvient que le SLO (Service Level Objective) de GCP est en 4×9 (99.99%) seulement, ceci explique donc cela, il faudra garder cet argument en tête lorsque nous comparerons avec les petits camarades AWS et Azure.

Supervision:

De notre point de vue de technicien, c’est là que l’on rentre vraiment dans le brouillard, si vous voulez bien me passer l’expression 🙂

Car si du point de vue du métier et des études, globalement Cloud SQL pour MySQL est une réussite du point de vue compatibilité et coût, du point de vue de la production c’est une autre paire de manches. Ce qui n’est pas surprenant, un service qui propose une infrastructure managée est censé s’affranchir des problématiques de production. Notre métier change, on le sait.

La question que l’on doit se poser toutefois, c’est quoi faire en cas de dégradation de performance. Le clouder vous dira avec le sourire que le plus simple reste de pousser le curseur à droite, partir sur un tier plus costaud, mais aussi une facture disons, plus conséquente.

Maintenant, votre intérêt sera de voir ce que vous pouvez optimiser avant de commencer à payer plus cher votre service. En mettant plus de ressources face à un problème de performance, on ne s’attaque pas à la cause racine, même dans le cloud.

Pour y arriver, il faut des outils pour pouvoir investiguer comme on pourrait le faire sur une installation traditionnelle. Et comme ce n’est pas dans l’intérêt du clouder, ces outils que l’on avait l’habitude manipuler vont commencer à se raréfier.

Faisons un tour de ce qui est disponible et ce qui ne l’est pas pour MySQL sur GCP:

Analyse de performance générale Disponibilité dans Cloud SQL
PERFORMANCE_SCHEMA Attention sur le choix du tier, performance_schema ne sera activable que pour les tiers supérieurs à db-n1-standard-8 ou db-n1-highmem-4, et ensuite on ne pourra plus redescendre sur une gamme inférieure.
VARIABLES DE STATUT OK, elles sont toutes là (370 variables en 5.7.14), interrogeables depuis un client avec pt-mext, donc rien ne change de ce point de vue.
SHOW ENGINE INNODB STATUS OK, toutes les sections sont là.
PARAMETRES ORIENTES PERFORMANCES Dans la liste des paramètres orientés performance, on notera que les paramètres mémoire type innodb_buffer_pool_size, innodb_buffer_pool_instances (partitionnement du cache, par défaut non partitionné), sort_buffer_size, table_open_cache, etc… ne seront pas positionnables. Ils sont vraisemblablement calculés en fonction du tier. Par contre tmp_table_size et max_heap_table_size sont disponibles, ainsi que query_cache_size ce qui est assez pratique si l’on souhaite désactiver le query cache.

Analyse de requêtes Disponibilité dans Cloud SQL
EXPLAIN OK
@@optimizer_switch Positionnable dans la session seulement, en raison du privilège SUPER qui empêche le SET GLOBAL. A noter que le multi range read est actif par défaut mais pas le Batch Key Access, qui ne sera positionnable que dans la session donc…
SET OPTIMIZER TRACE OK
Paramètres requêtes lentes Log_query_not_using_index, slow_query_log et long_query_time sont positionnables, ansi que log_output et general_log. Par défaut les requêtes lentes seront stockées dans un bucket accessible via le gestionnaire de logs de GCP, téléchargeables au format JSON et CSV. Assez peu pratique pour lancer un pt-query-digest ou un mysqldumpslow pour agréger les résultats. L’autre solution consiste à changer la destination de log_output et mettre TABLE à la place de FILE, mais avec les problèmes d’impact potentiel que cela suppose
SET PROFILING=1 Fonctionne OK. C’est toujours ça d’autant que le remplaçant désigné des PROFILES, à savoir Performance_schema, n’est pas disponible sur tous les tiers.

Quant aux outils proposés par GCP, un faible nombre de métriques est proposé sur la page d’accueil de l’instance :

Pour aller plus loin, il existe la brique Stackdriver qui est le service de supervision ‘maison’, il va proposer une trentaine de compteurs supplémentaires :

– Des compteurs infra PaaS : par exemple utilisation CPU, disque, mémoire, nombre de failovers, …

– Des compteurs spécialisés pour MySQL : 15 compteurs en tout :


Ces compteurs sont ensuite visibles soit dans des dashboards personnalisables ou dans le dashboard pour Cloud SQL par défaut. Mais cela reste assez limité, si vous voulez savoir si vos paramètres max_heap_table_size / tmp_table_size sont correctement dimensionnés, ou historiser les compteurs de l’optimiseur type handler etc…, il faudra le faire vous-mêmes. Je ne parle même pas des postes d’attente dans performance_schema. Il n’y a actuellement rien dans Stackdriver qui puisse se plugger sur performance_schema à l’heure actuelle.

On reste donc un peu sur sa faim d’autant que toutes les variables de statut sont disponibles, pourquoi ne pas toutes les proposer dans Stackdriver ?

MCO hors sauvegardes:

Concernant les statistiques, @@innodb_stats_persistent et @@innodb_stats_auto_recalc sont à 1 par défaut en 5.6.6 donc pas de différence par rapport à une instance on-premise. S’il y a besoin de calculer par table il est toujours possible de positionner des options par table, ou recalculer en utilisant l’event scheduler de MySQL qui est l’une des rares options utilisables dans Cloud SQL.

Concernant la fragmentation, tout est en InnoDB donc attention tout objet est clusterisé, sujet aux page splits et autres merge split, etc… Si on souhaite être proactif par rapport à ces problèmes ça va être compliqué car @@innodb_fill_factor est à 1 par défaut et ne pourra pas être modifié, on ne pourra changer le taux de remplissage des pages que via l’option MERGE_THRESHOLD et par table / index, donc au cas par cas. Rappelez-vous aussi que vous allez surprovisionner le stockage pour pouvoir obtenir de meilleures performances, donc vous risquez de passer à côté des problèmes fragmentation.

Enfin le problème de reconstruction des indexes secondaires dans le mauvais ordre persiste . Pas de paramètre @@expand_fast_index_creation sur Cloud SQL, si vous voulez absolument reconstruire régulièrement vos indexes, pensez à supprimer les indexes non clustered d’abord, recréez l’index cluster et recréez-les non clustered ensuite.

Migration vers Cloud SQL:

Deux solutions : soit vous pouvez vous permettre une indisponibilité et vous pouvez passer par un mysqldump classique pour migrer vos bases dans Cloud SQL, soit vous ne pouvez pas et vous pouvez passer par une réplication avec un master externe.

Je me m’attarderai pas sur la méthode via mysqldump. Il faut se rappeler que si vous récupérez vos triggers, procédures stockées, fonctions et vues par défaut un DEFINER sera généré et risque de provoquer des erreurs lors de l’import car cela nécessite le privilège SUPER.

Error Code : 1227
Access denied; you need (at least one of) the SUPER privilege(s) for this operation

Egalement certains morceaux de code peuvent nécessiter d’activer l’option @@log_bin_trust_function_creators qui est heureusement disponible dans la liste des paramètres modifiables dans Cloud SQL.

Si l’indisponibilité est un facteur dans la migration, alors il est possible de répliquer un master on-premise ou en mode IaaS vers un slave dans Cloud SQL. L’architecture sera telle que :

Vous noterez la présence d’une Source Representation Instance qui est en fait une instance proxy qui matérialise le master externe dans le PaaS. Elle ne contient pas de données.

Plusieurs choses à noter avant de passer à l’action:

1) On ne pourra pas filtrer en aval avec un replication filter de type replicate_do_db. Et pourquoi à votre avis ?

mysql> change replication filter replicate_do_db=(sakila) ;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation

Il faudra donc le faire en amont si vous ne souhaitez pas migrer toutes les bases via cette technique.

2) La réplication GTID est imposée, avec tout ce qui va avec : les paramètres gtid_mode et enforce_gtid_consistency doivent être activés sur le master, ainsi que log_slave_updates. Autre détail qui a son importance, GTID n’arrive qu’en 5.6.5, donc si vous êtes dans une version inférieure côté master, vous ne pourrez pas migrer en utilisant cette solution.

3) Les binlogs doivent évidemment être activés, en mode ROW.

La mise en place d’une réplication requiert donc 4 étapes :

1) Créer un compte avec le privilège replication slave sur le master pour que le thread IO puisse se connecter et collecter les transactions à répliquer dans les logs binaires.

mysql> grant replication slave on *.* to 'replgcp'@'%' identified by '********' ;
Query OK, 0 rows affected (0.36 sec)

Note : On ne connaît pas l’IP du slave à l’avance car l’instance n’est pas encore créée.

2) Une fois les applications stoppées, créer un backup via mysqldump et le stocker dans un bucket préalablement créé sur Cloud Storage :

$ mysqldump --login-path=capdata56 \
--databases sakila --hex-blob --skip-triggers \
--master-data=1 --order-by-primary \
--no-autocommit --default-character-set=utf8mb4 \
--single-transaction --set-gtid-purged=on \
| gzip | gsutil cp - gs://repl-cap-cloud-bucket/Sakila.2.GCP.dmp.gz

Warning: A partial dump from a server that has GTIDs will by default include 
the GTIDs of all transactions, even those that changed suppressed parts of 
the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. 
To make a complete dump, pass --all-databases --triggers --routines --events. 
Copying from <STDIN>...
/ [1 files][    0.0 B/    0.0 B]                                                
Operation completed over 1 objects.     

Le fichier est compressé et copié à la volée avec l’utilitaire gsutil qui fait partie de la suite CLI.

3) Créer la SRI:

$ gcloud beta sql instances create mysql56-src --region=europe-west4 \
--database-version=MYSQL_5_6 --source-ip-address=193.145.24.23 \
--source-port=5639
Creating Cloud SQL instance...done.
Created [https://www.googleapis.com/sql/v1beta4/projects/durable-epoch-220407/instances/mysql56-src].
NAME         DATABASE_VERSION  LOCATION      TIER  PRIMARY_ADDRESS  PRIVATE_ADDRESS  STATUS
mysql56-src  MYSQL_5_6         europe-west4        -                -

193.145.24.23, 5639 est l’IP publique et le port sur laquelle mon master externe est rendu accessible de l’extérieur, via une redirection de port ou autre artifice.

4) Enfin, créer le slave, l’initialiser avec le dump puis démarrer les thread IO et SQL (on se rappelle qu’on ne peut pas faire de CHANGE MASTER TO sur le slave, il faudra passer par l’utilitaire CLI ou la console).

capdata@mysql8:/home/capdata$ gcloud beta sql instances create mysql5-slv \
> --master-instance-name=mysql56-src \
> --master-username=replgcp --prompt-for-master-password \
> --master-dump-file-path=gs://repl-cap-cloud-bucket/Sakila.2.GCP.dmp \
> --tier=db-n1-standard-1 --storage-size=30 

WARNING: Starting with release 218.0.0, you will need to specify either a region or a zone to create an instance.
Master Instance Password: ************

Le slave va tenter de se connecter au master pendant 30 minutes au delà desquelles il va ensuite stopper et ne pourra plus être redémarré. Ce qui vous laisse un intervalle de temps pour récupérer l’IP publique du service nouvellement créé et paramétrer ce qu’il faut côté firewall et redirections de flux:

$ gcloud sql instances describe mysql5-slv --format="default(ipAddresses)"
ipAddresses:
- ipAddress: 35.224.167.132

Une fois le slave synchronisé, il ne vous reste plus qu’à planifier les modalités de bascule.

En conclusion:

Bravo si vous êtes arrivés jusque-là sans sauter de paragraphe 🙂

Pour tirer de vraies conclusions il faudra attendre de mettre l’offre PaaS de Google en perspective par rapport à celles de Microsoft et Amazon. Mais déjà on peut peut faire une liste Plus / Moins:

Les plus

– Haut niveau de compatibilité fonctionnelle avec la version classique, ce qui fonctionne globalement on-premise pourra être porté sans beaucoup de modifications dans le PaaS, or on sait que le coût de redéveloppement est souvent le premier poste d’une migration.
– Du point de vue technique ce n’est pas non plus la boite noire que l’on craignait. Certes Performance_schema n’est pas disponible pour tous les tiers mais beaucoup d’outils de diagnostic sont présents, avec la possibilité de se créer ses propres outils.
– Performances disque annoncées très bonnes (15000 IOPS / 240Mb/s).
– Gestion automatique de la reprise sur incident avec le failover replica et la VIP.
– Possibilité de migrer en utilisant la réplication avec un master externe.
– Gestion des fenêtres de maintenance

Les moins

– Pas possible de paramétrer la rétention des backups au delà de 7 jours
– Faible nombre de compteurs disponibles même dans Stackdriver.
– Manipulation du log de requêtes lentes compliqué. (export CSV, JSON, puis retraitement avant de lancer un pt-query-digest ou équivalent)
– Coupures de service aléatoires lors du passage de patches, et difficulté de maîtriser les impacts sur la production car pas de temps pour tester.
– Le prix du failover replica est le même que celui du master ou d’un read replica. L’addition peut monter rapidement en empilant les instances les unes sur les autres.

Dans le prochain épisode nous parlerons de MySQL dans le PaaS Azure, nous pourrons alors commencer à comparer un peu les deux offres. N’hésitez à nous faire part de vos commentaires et questions et abonnez-vous au flux RSS du blog pour la suite de nos aventures.

A bientôt !

Continuez votre lecture sur le blog :




Cliquer pour partager cet article sur Viadeo
Cliquer sur "CAPTURER" pour sauvegarder cet article dans Evernote Clip to Evernote

Tags: , ,

Leave a Reply