khôi phục một cơ sở dữ liệu mysql duy nhất trên một hệ thống sao chép nô lệ chủ bận rộn


10

Tìm kiếm một chiến lược hoặc công cụ để đối phó với việc khôi phục một cơ sở dữ liệu duy nhất đến một thời điểm trong một hệ thống được nhân rộng bận rộn.

Tôi có 12 cơ sở dữ liệu chạy trên 2 máy chủ MySQL 5.0.77 trong cấu hình nhân rộng master-Slave. Một bãi chứa đầy đủ được lấy từ nô lệ chỉ đọc hàng ngày và có sẵn các kết xuất SQL tăng dần, với các bản sao lưu này ngoài trang web và trạng thái sao chép được theo dõi.

Chỉnh sửa: Bảng là hỗn hợp của InnoDB và myISAM, do đó không có giải pháp cụ thể cho động cơ.

Vì vậy, khi máy chủ chính bị lỗi hoàn toàn, tôi có thể phá vỡ bản sao và quảng bá máy chủ nô lệ, tôi cũng có tùy chọn xây dựng lại máy chủ mới và định cấu hình từ bản sao lưu FULL việt vị, sau đó áp dụng các vi sai được lấy hàng giờ từ nô lệ.

Tuy nhiên tôi lo ngại làm thế nào để đối phó với thất bại một phần, hoặc thất bại của một cơ sở dữ liệu. Tôi có thể nghĩ về 2 kịch bản khá có khả năng;

  1. cơ sở dữ liệu 7 (ví dụ) bị hỏng, tiếp tục phục vụ một số yêu cầu cho đến khi ai đó nhận thấy rằng nó bị hỏng hoặc cảnh báo từ các tệp nhật ký ...
  2. Một số truy vấn như cơ sở dữ liệu thả, bảng thả, "cập nhật trong đó ..." loại truy vấn có một cơ sở dữ liệu hoặc một số tập hợp con trong đó.

Hiện tại tôi có một loạt các ĐẦY ĐỦ như các tệp FULL- $ DATE-all-cơ sở dữ liệu.sql.gz và các vi sai có thể được áp dụng cho các bãi chứa ĐẦY ĐỦ như DIFF- $ DATE-all-cơ sở dữ liệu.sql.gz

Để khôi phục cơ sở dữ liệu 7 về một số thời điểm sẽ cần một grep thông qua các tệp FULL và DIFF và ứng dụng thủ công của sql đó.

Tôi nên tiến hành như thế nào để có thể khôi phục lại một trong các bãi DIFF trước đó vào cơ sở dữ liệu chủ?

Tôi có cần sao lưu vào các tệp cơ sở dữ liệu cá nhân không, tức là

mysqldump --databases "database1" | gzip > database1.sql.gz
mysqldump --databases "database2" | gzip > database2.sql.gz
mysqldump --databases "database3" | gzip > database3.sql.gz

thay vì ..

mysqldump --master-data --lock--all-databases --all-databases | gzip > all-databases.sql.gz

Nếu tôi sử dụng các tệp mysqldump riêng biệt, điều gì sẽ xảy ra với nhật ký nhị phân dữ liệu chủ và thậm chí tôi có nên cài đặt --master-data cho các bãi phục hồi máy chủ chính không?

Câu trả lời:


7

Nếu tất cả cơ sở dữ liệu của bạn chỉ sử dụng InnoDB, tôi có một số tin tốt.

Bạn nên kết xuất tất cả các cơ sở dữ liệu song song từ một nô lệ.

Trong thực tế, bạn có thể buộc tất cả các cơ sở dữ liệu vào cùng một thời điểm.

Điều đầu tiên cần nhớ về Slave là không bắt buộc phải đăng nhập nhị phân nếu nó không phải là Master cho các nô lệ khác.

Bạn không thể sử dụng --master-datatùy chọn cho các bãi chứa song song vì mỗi bãi chứa sẽ có một vị trí khác nhau được ghi ở dòng 22 của mỗi tệp kết xuất. Tốt hơn là ghi lại tệp nhật ký cuối cùng của Master và định vị Slave được thực thi bằng cách sử dụng SHOW SLAVE STATUS\G. Bằng cách đó, tất cả các cơ sở dữ liệu có cùng một vị trí tại thời điểm.

Bạn có thể thu thập tất cả các cơ sở dữ liệu và kịch bản kết xuất song song của tất cả các cơ sở dữ liệu.

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
done 
wait 

mysql -h... -u... -p... -e"START SLAVE;"

Nếu đơn giản là có quá nhiều cơ sở dữ liệu, hãy kết xuất chúng 10 hoặc 20 tại một thời điểm như sau:

DBLIST=/tmp/ListOfDatabasesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql','performance_schema')" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DB in `cat ${DBLIST}` 
do 
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

Nếu bạn cần khôi phục một bảng duy nhất, bạn có thể kết xuất song song các bảng 20 tại một thời điểm theo thứ tự kích thước.

Thử đi:

TBLIST=/tmp/ListOfTablesToParallelDump.txt
SSS=/tmp/ShowSlaveStatusDisplay.txt
BACKUP_BASE=/backups
BACKUP_DATE=`date +"%Y%m%d_%H%M%S"`
BACKUP_HOME=${BACKUP_BASE}/${BACKUP_DATE}
mkdir ${BACKUP_HOME}
cd ${BACKUP_HOME}

mysql -h... -u... -p... -e"STOP SLAVE;"
mysql -h... -u... -p... -e"SHOW SLAVE STATUS\G" > ${SSS}
LOGFIL=`cat ${SSS} | grep "Relay_Master_Log_File" | awk '{print $2}'`
LOGPOS=`cat ${SSS} | grep "Exec_Master_Log_Pos"   | awk '{print $2}'`
echo "Master was at ${LOGFIL} Position ${LOGPOS} for this Backup" > Master_Log_FilePos.txt

mysql -h... -u... -p... -AN -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY data_length" > ${DBLIST}

COMMIT_LIMIT=20
COMMIT_COUNT=0    
for DBTB in `cat ${TBLIST}` 
do
    DB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo "${DBTB}" | sed 's/\./ /g' | awk '{print $2}'`
    DUMPFILE=$DB-{DB}-TBL-${TB}.sql.gz
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} ${TB} | gzip >  ${DUMPFILE} & 
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done 
wait 
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

mysql -h... -u... -p... -e"START SLAVE;"

Bây giờ bạn có các tập lệnh để kết xuất cơ sở dữ liệu hoặc các bảng riêng lẻ, bạn có thể tải dữ liệu đó theo ý của mình. Nếu bạn cần để SQL được thực thi từ các bản ghi nhị phân trên bản gốc, bạn có thể sử dụng mysqlbinlogvà đặt cho nó vị trí ot datetime và xuất SQL sang các tệp văn bản khác. Bạn chỉ cần thực hiện thẩm định để tìm ra lượng dữ liệu bạn cần từ bất kỳ dấu thời gian nào mà nhật ký bnary có. Chỉ cần nhớ rằng dấu thời gian của nhật ký nhị phân trong HĐH thể hiện lần cuối cùng được viết.


câu trả lời tuyệt vời thanx. Tôi nghĩ rằng có một nô lệ chỉ đọc trên xfs mang lại cho tôi vô số tùy chọn và các kịch bản của bạn đã thực sự có ích.
Tom H

trong kịch bản mà tôi cần khôi phục một bảng lớn cho chủ từ một bản sao lưu ra khỏi nô lệ. Tôi chỉ cần xây dựng lại bảng trên bản gốc và có tất cả các thay đổi được sao chép xuống nô lệ, ngay cả khi đó là 20GB dữ liệu? Quá trình có phải là 1) vô hiệu hóa các khóa, 2) thả bảng trên master và Slave 3) khôi phục lại bảng master 4) cho phép các khóa --- và có chủ nhân sao chép tất cả 20GB xuống nô lệ không?
Tom H

Nếu các cơ sở dữ liệu này KHÔNG phải là innodb, tôi vẫn có thể kết xuất chúng song song chứ?
Tom H

Có, nếu bạn 1) lên lịch ngừng hoạt động, 2) chạy service mysql restart --skip-networking, 3) thực hiện kết xuất song song, 4) chạy service mysql restart. Sau đó tải lại các bảng bạn cần.
RolandoMySQLDBA

có lẽ nếu mục đích của việc khởi động lại là để ngăn kết nối mạng ghi vào cơ sở dữ liệu, thì tôi có thể đạt được hiệu quả tương tự bằng cách sử dụng iptables i.e. iptables -I INPUT -p tcp --dport 3306 -j DROPtrên eth0 và lo
Tom H
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.