Cách an toàn nhất để thực hiện mysqldump trên một hệ thống trực tiếp với hoạt động đọc và ghi?


78

Tôi không chắc điều này có đúng không nhưng tôi nhớ đã đọc nếu bạn chạy lệnh sau trong linux

mysqldump -u username -p database_name > backup_db.sql

trong khi đọc và ghi đang được thực hiện cho cơ sở dữ liệu thì kết xuất có thể chứa lỗi.

Có các tùy chọn cụ thể trong lệnh mysqldumpđể đảm bảo việc này được thực hiện an toàn trên hệ thống trực tiếp không? Tôi ổn với việc đọc / ghi bị vô hiệu hóa cho người dùng của chúng tôi trong vài giây (Cơ sở dữ liệu <50MB)

Câu trả lời:


82

Tất cả dữ liệu là InnoDB

Đây là những gì sẽ cung cấp cho bạn một ảnh chụp nhanh thời gian chính xác của dữ liệu:

mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

--single-transactiontạo một điểm kiểm tra cho phép bãi chứa để thu thập tất cả dữ liệu trước điểm kiểm tra trong khi nhận được các thay đổi đến. Những thay đổi đến không trở thành một phần của bãi chứa. Điều đó đảm bảo cùng một thời điểm cho tất cả các bảng.

--routines bỏ tất cả các thủ tục được lưu trữ và các chức năng được lưu trữ

--triggers bỏ tất cả các kích hoạt cho mỗi bảng có chúng

Tất cả dữ liệu là MyISAM hoặc Mix of InnoDB / MyISAM

Bạn sẽ phải áp dụng khóa đọc toàn cầu, thực hiện mysqldump và phát hành khóa toàn cầu

mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print $1}'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql

Hãy thử một lần !!!

CẬP NHẬT 2012-06-22 08:12 EDT

Vì bạn có <50 MB tổng dữ liệu nên tôi có một tùy chọn khác. Thay vì khởi chạy lệnh SLEEP vào nền để giữ khóa đọc toàn cầu trong 86400 giây (tức là 24 giờ) chỉ để lấy ID tiến trình và tiêu diệt bên ngoài, hãy thử đặt thời gian chờ 5 giây trong mysql thay vì trong HĐH:

SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

Đây là một cách tiếp cận sạch hơn và đơn giản hơn cho các cơ sở dữ liệu rất nhỏ.


1
5 giây chỉ là phòng ngừa. Bạn có thể thử các giá trị thấp hơn.
RolandoMySQLDBA

1
Rolando - là ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during querymột thông báo lỗi dự kiến?
dùng784637

1
Có phải tất cả các dữ liệu MySQL xuất hiện trong mysqldump?
RolandoMySQLDBA

1
Tôi không chắc chắn về thông báo lỗi. Đây chỉ là một phỏng đoán, nhưng điều đó có thể đến từ tập lệnh một dòng sẽ giết cuộc gọi hàm SLEEP do người dùng định nghĩa mà tôi đã đề cập trong tập lệnh thứ hai.
RolandoMySQLDBA

1
Hãy thử đề xuất mới của tôi và xem nếu nó đi tốt. Hy vọng, sẽ không có thông báo lỗi.
RolandoMySQLDBA


1

Nếu bạn muốn làm điều này cho MyISAM hoặc các bảng hỗn hợp mà không có bất kỳ thời gian chết nào từ việc khóa các bảng, bạn có thể thiết lập cơ sở dữ liệu nô lệ và chụp ảnh nhanh từ đó. Thật không may, thiết lập cơ sở dữ liệu nô lệ, gây ra một số thời gian chết để xuất cơ sở dữ liệu trực tiếp, nhưng một khi nó đang chạy, bạn sẽ có thể khóa các bảng của nó và xuất bằng các phương thức mà người khác đã mô tả. Khi điều này xảy ra, nó sẽ tụt lại phía sau bản gốc, nhưng sẽ không ngăn chủ nhân cập nhật các bảng của nó và sẽ bắt kịp ngay khi bản sao lưu hoàn tất.


1

Đây là cách tôi đã làm nó. Nó nên hoạt động trong mọi trường hợp kể từ khi nó sử dụng FLUSH TABLES WITH READ LOCK.

#!/bin/bash

DB=example
DUMP_FILE=export.sql

# Lock the database and sleep in background task
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" &
sleep 3

# Export the database while it is locked
mysqldump -uroot -proot --opt $DB > $DUMP_FILE

# When finished, kill the previous background task to unlock
kill $! 2>/dev/null
wait $! 2>/dev/null

echo "Finished export, and unlocked !"

Lệnh shell sleepchỉ để đảm bảo rằng tác vụ nền chạy lệnh khóa mysql được thực thi trước khi mysqldump bắt đầu. Bạn có thể giảm xuống còn 1 giây và nó vẫn ổn. Tăng nó lên 30 giây và thử chèn một giá trị vào bất kỳ bảng nào từ một khách hàng khác trong 30 giây đó bạn sẽ thấy nó bị khóa.

Có 2 lợi thế khi sử dụng khóa nền thủ công này, thay vì sử dụng các mysqldumptùy chọn --single-transaction--lock-tables:

  1. Điều này khóa mọi thứ, nếu bạn đã trộn các bảng MyISAM / InnoDB.
  2. Bạn có thể chạy các lệnh khác ngoài mysqldumpthời gian khóa tương tự. Chẳng hạn, nó hữu ích khi thiết lập sao chép trên nút chính, bởi vì bạn cần có được vị trí nhật ký nhị phân với SHOW MASTER STATUS;trạng thái chính xác của kết xuất mà bạn đã tạo (trước khi mở khóa cơ sở dữ liệu), để có thể tạo nô lệ sao chép.


0

nếu bạn có một bảng MYISAM rất lớn và bạn cần đổ bảng mà không khóa và tránh tải máy chủ cao, bạn có thể sử dụng tập lệnh sau.

#!/bin/sh

my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000

read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
    [Yy]* ) break;;
    * ) echo "User cancel."; exit;;
esac

my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))

if [ ! $my_count ]
then
    echo "No records found"
    exit
fi

echo "Records in table ${my_db}.${my_table}: ${my_count}"

echo "" > $my_table.sql

max_progress=60

for (( limit=0; limit<=$my_count; limit+=$my_step )); do
    progress=$((max_progress * ( limit + my_step) / my_count))

    echo -ne "Dumping ["
    for ((i=0; i<$progress; i ++)); do
        echo -ne "#"
    done
    for ((; i<$max_progress; i ++)); do
        echo -ne "."
    done

    mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
    echo "" >> $my_table.sql

    echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
    echo -ne "\r"

    sleep 1

done

echo -ne "\n"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.