All Products
Search
Document Center

Elastic Compute Service:Praktik terbaik untuk membuat snapshot konsisten aplikasi untuk MySQL (Linux)

Last Updated:Apr 02, 2026

Snapshot konsisten aplikasi secara sementara menangguhkan operasi penulisan database sebelum merekam status disk, memastikan data yang dipulihkan identik dengan kondisi pada saat pembuatan snapshot. Panduan ini menjelaskan langkah-langkah membuat snapshot konsisten aplikasi untuk instance ECS CentOS 7.9 yang menjalankan MySQL 8.0, lalu memverifikasi bahwa data yang dipulihkan sesuai dengan kondisi yang diharapkan.

Tingkat konsistensi snapshot

Tidak semua snapshot menjamin integritas data untuk database yang sedang berjalan. Memahami perbedaannya membantu Anda memilih pendekatan pencadangan yang tepat:

TypeWhat it capturesDatabase safety
Crash-consistentStatus disk pada suatu titik waktuData di memori atau operasi I/O yang tertunda mungkin hilang
Application-consistentStatus disk setelah membuang data di memori dan menangguhkan penulisanData berada dalam kondisi bersih dan dapat dipulihkan — aplikasi dapat dimulai ulang tanpa error

Untuk MySQL dan database transaksional lainnya, snapshot konsisten aplikasi adalah pilihan yang tepat.

Prasyarat

Sebelum memulai, pastikan Anda telah memiliki:

Saat membuat snapshot konsisten aplikasi, Cloud Assistant menjalankan perintah pada instance Anda untuk mengeksekusi prescript dan postscript. Peran RAM memberikan izin yang diperlukan kepada Cloud Assistant.

Kebijakan kustom yang dilampirkan ke peran RAM harus mencakup izin berikut:

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

Cara kerja

image

Alur kerja terdiri dari lima langkah:

  1. Buat prescript dan postscript — Prescript membersihkan tabel MySQL dan mengunci pembacaan global sebelum pembuatan snapshot. Postscript menghentikan proses yang memegang kunci untuk melanjutkan operasi penulisan setelah snapshot selesai.

  2. Persiapkan lingkungan verifikasi — Buat tabel database dan prosedur tersimpan yang mensimulasikan penulisan berkelanjutan. Hal ini memberikan garis waktu data yang diketahui untuk diverifikasi setelah pemulihan.

  3. Buat snapshot konsisten aplikasi — Di Konsol ECS, konfigurasikan pembuatan snapshot agar menjalankan skrip Anda dan menangguhkan sementara I/O sistem file.

  4. Verifikasi pembuatan snapshot — Konfirmasi Cloud Assistant berhasil mengeksekusi skrip dan identifikasi waktu pasti ketika penulisan ditangguhkan dan dilanjutkan.

  5. Verifikasi pemulihan data — Kembalikan disk Anda menggunakan snapshot, lalu kueri database untuk memastikan catatan terakhir yang ditulis mendahului jendela penangguhan.

Prosedur

Langkah 1: Buat prescript dan postscript

Penting

Skrip dalam panduan ini disediakan sebagai implementasi referensi. Sesuaikan skrip tersebut agar sesuai dengan kebutuhan aplikasi Anda. Untuk panduan umum, lihat Buat snapshot konsisten aplikasi.

Kedua skrip harus dimiliki oleh root dan memiliki izin chmod 700 (baca, tulis, dan eksekusi hanya untuk root). Jika izin tidak diatur dengan benar, skrip tidak akan dijalankan.

Buat /tmp/prescript.sh

  1. Hubungkan ke instance ECS sebagai pengguna root. Lihat Hubungkan ke instance Linux.

  2. Buat dan buka file prescript:

    vim /tmp/prescript.sh
  3. Tekan I untuk masuk ke mode Insert dan tempel skrip berikut. Ganti $MYSQL_USER dengan username MySQL Anda dan $MYSQL_PASSWORD dengan password MySQL Anda.

    Lihat isi prescript.sh

    TIMESTAMP=`date +%s`
    MYSQL_TEMP_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.tmp"
    LOG_FILE_NAME="/tmp/mysqlfreeze${TIMESTAMP}.log"
    
    # Masukkan username MySQL Anda.
    export MYSQL_USER="$MYSQL_USER"
    # Masukkan password MySQL Anda.
    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   >> "${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 -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

    Parameter yang perlu diperbarui:

    ParameterDescription
    $MYSQL_USERUsername MySQL Anda
    $MYSQL_PASSWORDPassword MySQL Anda
  4. Tekan Esc, ketik :wq, lalu tekan Enter untuk menyimpan file.

  5. Atur izin agar hanya root yang dapat membaca, menulis, dan mengeksekusi file:

    Penting

    chmod 700 wajib digunakan. Izin yang lebih luas menyebabkan pemeriksaan izin gagal dan skrip tidak akan dijalankan.

    chmod 700 /tmp/prescript.sh

Buat /tmp/postscript.sh

  1. Buat dan buka file postscript:

    vim /tmp/postscript.sh
  2. Tekan I untuk masuk ke mode Insert dan tempel skrip berikut. Ganti $MYSQL_USER dengan username MySQL Anda dan $MYSQL_PASSWORD dengan password MySQL Anda.

    Lihat isi postscript.sh

    TIMESTAMP=`date +%s`
    MYSQL_TEMP_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.tmp"
    LOG_FILE_NAME="/tmp/mysqlthaw${TIMESTAMP}.log"
    # Masukkan username MySQL Anda.
    export MYSQL_USER="$MYSQL_USER"
    # Masukkan password MySQL Anda.
    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

    Parameter yang perlu diperbarui:

    ParameterDescription
    $MYSQL_USERUsername MySQL Anda
    $MYSQL_PASSWORDPassword MySQL Anda
  3. Tekan Esc, ketik :wq, lalu tekan Enter untuk menyimpan file.

  4. Atur izin:

    chmod 700 /tmp/postscript.sh

Verifikasi izin skrip

Buka direktori /tmp dan pastikan kedua file memiliki izin 700:

cd /tmp
ls -l

Output yang muncul seharusnya mirip seperti berikut:

image

Langkah 2: Persiapkan lingkungan verifikasi database

Langkah ini membuat tabel dan prosedur tersimpan yang memasukkan satu catatan per detik selama 3 menit. Menjalankan prosedur ini sebelum membuat snapshot memberikan garis waktu referensi untuk diverifikasi setelah rollback.

Penting

Buat snapshot konsisten aplikasi saat prosedur tersimpan TestPIT sedang berjalan. Prosedur ini berjalan selama 3 menit — Anda harus menyelesaikan Langkah 3 dalam rentang waktu tersebut.

  1. Buat skrip uji di /root/test.sql:

    vim /root/test.sql
  2. Tekan I, tempel konten berikut, lalu tekan Esc dan ketik :wq untuk menyimpan:

    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 ;
  3. Login ke MySQL:

    mysql -u <mysqlUserName> -p

    Ganti <mysqlUserName> dengan username MySQL Anda, lalu masukkan password Anda saat diminta.

  4. Buat database AdventureWorks:

    CREATE DATABASE AdventureWorks;
  5. Jalankan skrip uji:

    source /root/test.sql
  6. Panggil prosedur tersimpan untuk mulai menulis catatan:

    CALL TestPIT;

    Dengan TestPIT sedang berjalan, segera lanjutkan ke Langkah 3.

Langkah 3: Buat snapshot konsisten aplikasi

Buka Konsol ECS - Snapshot-consistent Groups.

  1. Di bilah navigasi atas, pilih wilayah dan kelompok sumber daya untuk instance Anda.

    Region

  2. Pada tab Snapshot-consistent Groups, klik Create Snapshot-consistent Group.

  3. Pada kotak dialog Create Snapshot:

    1. Biarkan Resource Type tetap sebagai Instance.

    2. Pilih instance Anda dari daftar drop-down Select Instances. Pada bagian Select Cloud Disks, pilih ESSD yang ingin disertakan dalam snapshot.

    3. Bentangkan Advanced Settings.

    4. Pilih Enable Application-consistent Snapshot.

    5. Atur path prescript dan postscript agar sesuai dengan file yang Anda buat di Langkah 1: /tmp/prescript.sh dan /tmp/postscript.sh.

    6. Pilih Enable untuk fitur File System I/O Suspension and Resume dan atur periode timeout.

  4. Klik OK.

Setelah grup snapshot-konsisten dibuat, pesan konfirmasi akan menampilkan ID perintah dan ID tugas Cloud Assistant. Gunakan ID tugas tersebut pada langkah berikutnya untuk memverifikasi hasilnya.

Langkah 4: Verifikasi pembuatan snapshot

  1. Di halaman Cloud Assistant ECS, klik ID tugas untuk melihat hasil eksekusi perintah. Jika skrip berhasil dijalankan, ExitCode bernilai 0 dan output mencantumkan ID snapshot serta ID grup snapshot-konsisten. Jika ExitCode bukan 0, gunakan tabel berikut untuk pemecahan masalah: Untuk referensi lengkap kode kesalahan, lihat Kode kesalahan.

    ExitCodeLikely causeAction
    1 (prescript)MySQL sudah dibekukan, koneksi gagal, atau pembekuan timeout setelah 10 percobaanPeriksa log prescript di /tmp/mysqlfreeze<timestamp>.log untuk baris [ERROR] spesifik
    1 (postscript)Tidak ditemukan proses pembekuan, atau perintah kill gagalPeriksa log postscript di /tmp/mysqlthaw<timestamp>.log. Verifikasi secara manual apakah MySQL sedang berjalan dengan systemctl status mysqld.service
    Permission errorIzin skrip bukan 700, atau skrip tidak dimiliki oleh rootJalankan ulang chmod 700 dan verifikasi kepemilikan dengan ls -l /tmp/prescript.sh

    image

  2. Dalam output Cloud Assistant, identifikasi kapan penulisan ditangguhkan dan dilanjutkan:

    • Prescript dimulai pada 2024-08-27 15:27:55 — penulisan ditangguhkan pada waktu ini. image

    • Postscript selesai pada 2024-08-27 15:27:57 — penulisan dilanjutkan pada waktu ini. image

  3. Konfirmasi snapshot diberi tag sebagai konsisten aplikasi: Buka Konsol ECS - Snapshot-consistent Groups. Pada tab Snapshot-consistent Groups, klik ID grup snapshot-konsisten. Di bagian Snapshot Information, periksa kolom Tag untuk setiap snapshot. Snapshot yang diberi tag APPConsistent:True merupakan snapshot konsisten aplikasi.

    image

  4. Hubungkan ke MySQL dan konfirmasi tidak ada penyisipan yang terjadi selama jendela penangguhan:

    1. Hubungkan ke instance ECS. Lihat Hubungkan ke instance Linux.

    2. Login ke MySQL:

      mysql -u <mysqlUserName> -p
    3. Kueri tabel PointInTime:

      USE AdventureWorks;
      SELECT * FROM PointInTime;
    4. Dalam hasilnya, verifikasi tidak ada catatan antara 2024-08-27 15:27:55 dan 2024-08-27 15:27:58. Celah ini mengonfirmasi database ditangguhkan selama pembuatan snapshot. image

Langkah 5: Verifikasi pemulihan data

  1. Kembalikan disk menggunakan grup snapshot-konsisten. Lihat Kembalikan disk menggunakan grup snapshot-konsisten.

  2. Hubungkan ke instance ECS. Lihat Hubungkan ke instance Linux.

  3. Login ke MySQL:

    mysql -u <mysqlUserName> -p
  4. Kueri tabel PointInTime:

    USE AdventureWorks;
    SELECT * FROM PointInTime;
  5. Periksa timestamp catatan terakhir. Interpretasikan hasilnya: Dalam contoh output, catatan terakhir berada pada 2024-08-27 15:27:54, yang lebih awal daripada waktu mulai prescript yaitu 2024-08-27 15:27:55. Snapshot konsisten aplikasi berhasil membackup data MySQL.

    Last record timestampMeaning
    Lebih awal dari 2024-08-27 15:27:55 (waktu mulai prescript)Tidak ada penulisan yang terjadi selama penangguhan. Snapshot berhasil menangkap kondisi database — pemulihan berhasil.
    Sama dengan atau lebih baru dari 2024-08-27 15:27:55Penulisan terjadi selama jendela penangguhan. Data snapshot tidak konsisten dengan titik pembekuan yang diharapkan.

    image