Tous les produits
Search
Centre de documentation

Elastic Compute Service:Créer des snapshots cohérents au niveau de l'application pour MySQL sur Linux

Dernière mise à jour :Sep 22, 2026

Utilisez une instance CentOS 7.9 avec MySQL 8.0 pour créer et vérifier des snapshots cohérents au niveau de l'application qui empêchent la corruption des données lors de la sauvegarde.

Prérequis

  • L'instance ECS utilise des disques ESSD et la fonctionnalité multi-attach est désactivée pour les disques.

  • L'instance ECS est à l'état Running. Cloud Assistant est à l'état Normal sur l'instance. Pour afficher l'état de Cloud Assistant, consultez Vérifier l'état de Cloud Assistant et résoudre les exceptions.

  • MySQL est installé et vous disposez du nom d'utilisateur et du mot de passe de la base de données. Consultez Déployer manuellement une base de données MySQL (Linux).

  • Un rôle RAM avec une stratégie personnalisée pour les snapshots cohérents au niveau de l'application est associé à l'instance ECS. Consultez Créer un rôle RAM et l'associer à une instance ECS.

    Remarque

    Cloud Assistant nécessite des autorisations spécifiques pour accéder à l'instance ECS et exécuter des commandes. Accordez ces autorisations via le rôle RAM.

    • Configurez un rôle RAM personnalisé, tel que AppSnapshotRoleName.

    • Associez une stratégie personnalisée au rôle RAM. La stratégie d'exemple suivante accorde des autorisations pour interroger les snapshots, créer des snapshots, ajouter des tags et interroger les informations sur les disques.

      {
          "Version": "1",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "ecs:DescribeSnapshot*",
                      "ecs:CreateSnapshot*",
                      "ecs:TagResources",
                      "ecs:DescribeDisks"
                  ],
                  "Resource": [
                      "*"
                  ],
                  "Condition": {}
              }
          ]
      }

Flux de travail

Le flux de travail suivant crée un snapshot cohérent au niveau de l'application et vérifie que la base de données est restaurée à l'état exact capturé au moment du snapshot :

image
  1. Étape 1 : Créer les scripts prescript.sh et postscript.sh

    Créez un script pre-script (prescript.sh) pour suspendre les écritures dans la base de données et un script post-script (postscript.sh) pour les reprendre. Ces scripts sont requis pour les snapshots cohérents au niveau de l'application.

  2. Étape 2 : Préparer l'environnement de vérification de la base de données

    Créez une table de base de données et une procédure stockée (TestPIT) qui simulent des écritures continues, afin de pouvoir vérifier l'efficacité du snapshot après la restauration.

  3. Étape 3 : Créer un snapshot cohérent au niveau de l'application dans la console

    Créez un snapshot cohérent au niveau de l'application pour l'instance Linux qui héberge MySQL. Le pre-script et le post-script suspendent et reprennent temporairement les écritures dans la base de données pour garantir la cohérence des données.

  4. Étape 4 : Vérifier que le snapshot cohérent au niveau de l'application est créé

    Vérifiez les résultats de l'exécution de la commande Cloud Assistant. Notez les heures de suspension et de reprise de la base de données.

  5. Étape 5 : Vérifier la restauration des données à partir du snapshot cohérent au niveau de l'application

    Restaurez le disque à l'aide du snapshot. Comparez l'heure de la dernière écriture de données dans MySQL avec l'heure d'exécution de prescript.sh pour vérifier la bonne restauration des données.

    • Si l'heure de la dernière écriture est antérieure à l'heure d'exécution du pre-script, aucune écriture n'a eu lieu pendant la suspension. Les données restaurées correspondent à l'état du snapshot.

    • Si l'heure de la dernière écriture est identique ou postérieure à l'heure d'exécution du pre-script, des écritures ont eu lieu pendant la suspension, ce qui indique que le snapshot n'a pas fonctionné comme prévu.

Procédure

Étape 1 : Créer les scripts prescript.sh et postscript.sh

Important

Les scripts prescript.sh et postscript.sh présentés dans cette rubrique sont fournis à titre d'exemple uniquement. Rédigez des scripts adaptés à vos besoins métier réels. Consultez Créer un snapshot cohérent au niveau de l'application.

  1. Connectez-vous à l'instance ECS en tant qu'utilisateur root.

    Consultez Se connecter à une instance Linux à l'aide de Workbench.

  2. Créez /tmp/prescript.sh et ajoutez le contenu du script.

    1. Créez /tmp/prescript.sh en tant que root.

      vim /tmp/prescript.sh
    2. Appuyez sur i pour passer en mode édition.

    3. Personnalisez le contenu de prescript.sh pour votre application.

      Contenu de prescript.sh

      TIMESTAMP=`date +%s`
      MYSQL_TEMP_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.tmp"
      LOG_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.log"
      
      # Set your MySQL username
      export MYSQL_USER="$MYSQL_USER"
      # Set your MySQL password
      export MYSQL_PWD="$MYSQL_PASSWORD"
      
      function Log()
      {
          echo "$1" 
          echo "$1" >> ${LOG_FILE_NAME}
      }
      
      function ExitWithResult()
      {
          Log "[INFO]:mysql freeze result is $1."
          exit $1
      }
      
      function Main()
      {
          Log "*********************************************************************"
          Log "[INFO]:Begin to freeze mysql."
      
          which mysql
          if [ $? -ne 0 ]
          then
              Log "[INFO]:mysql is not installed."
              ExitWithResult 0
          fi  
      
          systemctl status mysqld.service | grep "inactive (dead)"
          if [ $? -ne 1 ]
          then
              Log "[ERROR]:mysql is not running."
              ExitWithResult 0
          fi  
      
          mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
          if [ $? -ne 0 ]
          then
              cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
              [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
              Log "[ERROR]:Show process list failed."
              ExitWithResult 1
          fi
      
          process_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
          if [ "$process_id" != "" ]
          then
              cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
              [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
              Log "[ERROR]:MySQL already been freezed "
              ExitWithResult 1
          fi
      
          cat ${MYSQL_TEMP_FILE_NAME}
      
          Log "[INFO]:Try to execute flush tables command"
      
             echo "flush tables with read lock;select 1 and sleep(25);" | nohup mysql -u$MYSQL_USER -p$MYSQL_PASSWORD >> "${LOG_FILE_NAME}" 2>&1 &
          if [ $? -ne 0 ]
          then
              Log "[ERROR]:Freeze mysql failed."
              ExitWithResult 1
          fi  
      
          Log "[INFO]:Flush tables command execute success"
      
          checkTime=0
          while [ 1 ]
          do
              mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
              if [ $? -ne 0 ]
              then
                  cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
                  [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
                  Log "[ERROR]:Show process list failed."
                  ExitWithResult 1
              fi
              
              cat ${MYSQL_TEMP_FILE_NAME}
      
              process_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
              if [ "$process_id" = "" ]
              then
                  checkTime=`expr $checkTime + 1`
                  Log "[INFO]:Mysql is not freeze. checkTime is ${checkTime}"
                  sleep 1
              else
                  Log "[INFO]:Found sleep command in processlist,freeze success"
                  break
              fi
      
                 if [ $checkTime -eq 10 ]
              then
                  cat "${MYSQL_TEMP_FILE_NAME}" >>"${LOG_FILE_NAME}" 2>&1
                  
                  freeze_id=`cat ${MYSQL_TEMP_FILE_NAME} | grep "flush tables with read lock" | awk -F " " '{print $1}'`            
                  mysql -u$MYSQL_USER -p$MYSQL_PASSWORD -e "kill $freeze_id;" >> "${LOG_FILE_NAME}" 2>&1
                  if [ $? -ne 0 ]
                  then
                      Log "[ERROR]:Thaw mysql failed."
                  fi    
      
                  [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
                  Log "[ERROR]:Mysql is not freeze. Will return error"
                  ExitWithResult 1
              fi
          done
      
             [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
          Log "[INFO]:Finish freeze mysql."
          ExitWithResult 0
      }
      Main

      Modifiez les paramètres suivants :

      • $MYSQL_USER : Votre nom d'utilisateur MySQL.

      • $MYSQL_PASSWORD : Votre mot de passe MySQL.

    4. Appuyez sur Esc, saisissez :wq et appuyez sur Entrée pour enregistrer et quitter.

    5. Définissez les autorisations sur 700 (root uniquement).

      Important

      Seul l'utilisateur root doit disposer des autorisations de lecture, d'écriture et d'exécution (700). Sinon, l'exécution du script échoue.

      chmod 700 /tmp/prescript.sh
  3. Créez /tmp/postscript.sh et ajoutez le contenu du script.

    1. Créez /tmp/postscript.sh en tant que root.

      vim /tmp/postscript.sh
    2. Appuyez sur i pour passer en mode édition.

    3. Personnalisez le contenu de postscript.sh pour votre application.

      Contenu de postscript.sh

      TIMESTAMP=`date +%s`
      MYSQL_TEMP_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.tmp"
      LOG_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.log"
      # Set your MySQL username
      export MYSQL_USER="$MYSQL_USER"
      # Set your MySQL password
      export MYSQL_PWD="$MYSQL_PASSWORD"
      
      function Log()
      {
          echo "$1" 
          echo "$1" >> ${LOG_FILE_NAME}
      }
      
      function ExitWithResult()
      {
          Log "[INFO]:mysql unfreeze result is $1."
          exit $1
      }
      
      function Main()
      {
          Log "*********************************************************************"
          Log "[INFO]:Begin to thaw mysql."   
      
          which mysql
          if [ $? -ne 0 ]
          then
              Log "[INFO]:mysql is not installed."
              ExitWithResult 0
          fi  
      
          systemctl status mysqld.service | grep "inactive (dead)"
          if [ $? -ne 1 ]
          then
              Log "[ERROR]:mysql is not running."
              ExitWithResult 0
          fi  
      
          mysql -u$MYSQL_USER  -e "show processlist;" > "${MYSQL_TEMP_FILE_NAME}" 2>&1
          if [ $? -ne 0 ]
          then
              cat ${MYSQL_TEMP_FILE_NAME} >>"${LOG_FILE_NAME}"
              [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
              Log "[ERROR]:show process list failed."
              ExitWithResult 1
          fi
      
          Log "[INFO]:show process list success."
      
          cat ${MYSQL_TEMP_FILE_NAME}
          
          process_ids=`cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'`
          if [ "$process_ids" = "" ]
          then
              [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
              Log "[ERROR]:Get freeze process_id failed."
              ExitWithResult 1
          fi
      
          cat ${MYSQL_TEMP_FILE_NAME} | grep "select 1 and sleep(25)" | awk -F " " '{print $1}'| while read pid
          do
              Log "[INFO]:Try to stop sql process ${pid}."
      
              mysql -u$MYSQL_USER  -e "kill $pid;" >> "${LOG_FILE_NAME}" 2>&1
              if [ $? -ne 0 ]
              then
                  [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
                  Log "[ERROR]:Thaw mysql failed.PIDs is ${process_ids}"
                  ExitWithResult 1
              fi   
              Log "[INFO]:Stop sql process ${pid} success."
      
          done 
          
          [ -f ${MYSQL_TEMP_FILE_NAME} ] && rm -rf ${MYSQL_TEMP_FILE_NAME}
          Log "[INFO]:Finish thaw mysql."
          ExitWithResult 0
      }
      Main

      Modifiez les paramètres suivants :

      • $MYSQL_USER : Votre nom d'utilisateur MySQL.

      • $MYSQL_PASSWORD : Votre mot de passe MySQL.

    4. Appuyez sur Esc, saisissez :wq et appuyez sur Entrée pour enregistrer et quitter.

    5. Définissez les autorisations sur 700 (root uniquement).

      Important

      Seul l'utilisateur root doit disposer des autorisations de lecture, d'écriture et d'exécution (700). Sinon, l'exécution du script échoue.

      chmod 700 /tmp/postscript.sh
  4. Accédez à /tmp et vérifiez les autorisations des scripts.

    cd /tmp
    ls -l

    La sortie suivante indique que les autorisations sont correctes.

    image

Étape 2 : Préparer l'environnement de vérification de la base de données

  1. Créez le script de test /root/test.sql.

    1. Créez et ouvrez /root/test.sql.

      vim /root/test.sql
    2. Appuyez sur i pour passer en mode édition.

    3. Ajoutez le script SQL de vérification.

      Le script crée une table (PointInTime) et une procédure stockée (TestPIT) :

      USE AdventureWorks;
      CREATE TABLE PointInTime(id int, t datetime);
      DELIMITER $$
      CREATE PROCEDURE `TestPIT`()
      BEGIN
      DECLARE i int;
      SET i=1;
      WHILE i < 180
      DO
      INSERT INTO PointInTime VALUES(i, now());
      SELECT SLEEP(1);
      SET i=i+1;
      END WHILE;
      END $$
      DELIMITER ;
    4. Appuyez sur Esc, saisissez :wq et appuyez sur Entrée pour enregistrer et quitter.

  2. Connectez-vous à MySQL.

    Exécutez la commande suivante et saisissez le mot de passe MySQL lorsque vous y êtes invité.

    mysql -u <mysqlUserName> -p

    Remplacez <mysqlUserName> par votre nom d'utilisateur MySQL.

  3. Créez une base de données nommée AdventureWorks.

    CREATE DATABASE AdventureWorks;
  4. Exécutez le script de test.

    source /root/test.sql
  5. Appelez la procédure stockée (TestPIT).

    CALL TestPIT;
    Important

    Vous devez créer le snapshot cohérent au niveau de l'application avant la fin de TestPIT. La procédure s'exécute pendant environ 3 minutes.

Étape 3 : Créer un snapshot cohérent au niveau de l'application dans la console

  1. Accédez à Console ECS - groupe de snapshots cohérents.

  2. Dans le coin supérieur gauche de la page, sélectionnez une région et un groupe de ressources.

  3. Dans l'onglet Snapshot-consistent Groups, cliquez sur Create Snapshot-consistent Group.

  4. Dans la boîte de dialogue Create Snapshot, configurez le groupe de snapshots cohérents.

    1. Resource Types est défini par défaut sur Instance.

    2. Sélectionnez l'instance et ses disques ESSD.

    3. Développez Advanced Settings et activez le snapshot cohérent au niveau de l'application.

      1. Sélectionnez Enable Application-consistent Snapshot.

      2. Définissez les chemins d'accès vers prescript.sh et postscript.sh en utilisant les scripts créés à l'Étape 1.

      3. Définissez la durée pour File System I/O Pause and Resume.

  5. Cliquez sur OK.

    La commande renvoie un ID d'exécution Cloud Assistant. Utilisez cet ID pour afficher le résultat de l'exécution.

Étape 4 : Vérifier que le snapshot cohérent au niveau de l'application est créé

  1. Cliquez sur l'ID d'exécution Cloud Assistant pour afficher le résultat.

    image

    Un Exit Code de 0 indique que le snapshot a été créé avec succès. La sortie affiche les IDs du snapshot et du groupe de snapshots cohérents.

    Remarque

    Si le Exit Code n'est pas 0, résolvez le problème en fonction du code d'erreur du Exit Code. Consultez Codes d'erreur.

  2. Affichez les heures de suspension et de reprise de la base de données dans la sortie Cloud Assistant.

    Recherchez l'heure de début de prescript.sh et l'heure de fin de postscript.sh.

    • Le prescript.sh s'est exécuté à 2024-08-27 15:27:55, ce qui indique que la base de données a suspendu les écritures à ce moment-là.image

    • Le postscript.sh s'est exécuté à 2024-08-27 15:27:57, ce qui indique que la base de données a repris les écritures à ce moment-là.

      image

  3. Affichez le groupe de snapshots cohérents et le snapshot de disque.

    1. Accédez à Console ECS - groupe de snapshots cohérents.

    2. Dans l'onglet Snapshot-consistent Groups, cliquez sur l'ID du groupe de snapshots cohérents pour afficher les détails.

    3. Dans la section Snapshot Information, vérifiez que le tag du snapshot confirme la cohérence au niveau de l'application.

      Le tag du snapshot de disque APPConsistent:True confirme qu'un snapshot cohérent au niveau de l'application a été créé.

      image

  4. Connectez-vous à MySQL et vérifiez l'heure de suspension de la validation des données.

    1. Connectez-vous à l'instance ECS.

      Consultez Se connecter à une instance Linux à l'aide de Workbench.

    2. Connectez-vous à MySQL.

      Exécutez la commande suivante et saisissez le mot de passe MySQL lorsque vous y êtes invité.

      mysql -u <mysqlUserName> -p

      Remplacez <mysqlUserName> par votre nom d'utilisateur MySQL.

    3. Interrogez la table PointInTime.

      USE AdventureWorks;
      SELECT * FROM PointInTime;
    4. Affichez l'heure de suspension de la base de données dans les résultats de la requête.

      Aucune donnée n'a été insérée entre 2024-08-27 15:27:55 et 2024-08-27 15:27:58.

      image

Étape 5 : Vérifier la restauration des données à partir du snapshot cohérent au niveau de l'application

  1. Restaurez le disque à l'aide du groupe de snapshots cohérents.

  2. Connectez-vous à MySQL et interrogez la table PointInTime.

    1. Connectez-vous à l'instance ECS.

      Consultez Se connecter à une instance Linux à l'aide de Workbench.

    2. Connectez-vous à MySQL.

      Exécutez la commande suivante et saisissez le mot de passe MySQL lorsque vous y êtes invité.

      mysql -u <mysqlUserName> -p

      Remplacez <mysqlUserName> par votre nom d'utilisateur MySQL.

    3. Interrogez la table PointInTime.

      USE AdventureWorks;
      SELECT * FROM PointInTime;
    4. Affichez l'horodatage du dernier enregistrement après la restauration des données.

      Le dernier enregistrement a été inséré à 2024-08-27 15:27:54, soit avant l'heure de suspension 2024-08-27 15:27:55 notée à l'Étape 4. Cela confirme que les données ont été correctement restaurées à partir du snapshot cohérent au niveau de l'application.

      image