Sao lưu cơ sở dữ liệu MySQL thông qua ảnh chụp nhanh ZFS


12

Tôi đã tìm thấy một số trang web nói về việc thực hiện chính xác điều này, nhưng tôi thiếu một vài chi tiết quan trọng. Các bước chung là

  • Chạy FLUSH TABLES WITH READ LOCK
  • Chụp ảnh nhanh ZFS
  • Chạy UNLOCK TABLES

Nhiều nguồn báo cáo rằng InnoDB, mà tôi đang sử dụng, không thực sự tôn vinh a FLUSH. Hướng dẫn sử dụng MySQL lưu ý rằng có một FLUSH TABLES...FOR EXPORTbiến thể để sử dụng với InnoDB, nhưng yêu cầu chỉ định từng bảng riêng lẻ, thay vì sao lưu toàn bộ cơ sở dữ liệu. Tôi muốn tránh chỉ định từng bảng riêng lẻ vì rất có thể danh sách các bảng sẽ không đồng bộ với các bảng thực sự tồn tại.

Vấn đề khác tôi có là tôi dự định làm một cái gì đó như thế nào mysql -h"$HOST" -u"$USERNAME" -p"$PASSWORD" --execute="FLUSH TABLES WITH READ LOCK". Tuy nhiên, điều này làm giảm khóa ngay sau khi thoát phiên. Điều này có ý nghĩa, nhưng cũng khá khó chịu vì tôi cần phải giữ khóa đọc khi tôi chụp ảnh.

Ý tưởng khác của tôi là sao lưu dự phòng bằng cách sử dụng một công cụ như Percona XtraBackup và chụp ảnh sao lưu, nhưng tôi không muốn trả chi phí để ghi tất cả dữ liệu của mình vào vị trí thứ hai chỉ để chụp.


Tại sao có một danh sách tĩnh của các bảng? Bạn chắc chắn có thể tạo một danh sách động khi chạy.
EEAA

1
Là cơ sở dữ liệu trên máy ảo hoặc trên kim loại trần? Là lưu trữ ngay cả trên cùng một máy?
Michael Hampton

EEAA, đủ công bằng.
Andy Shulman

Michael, cơ sở dữ liệu và hộp ZFS là các máy khác nhau, nhưng không phải là ảo hóa.
Andy Shulman

@AndyShulman Tôi nghĩ bạn nên giải thích bố cục tốt hơn một chút. Điều này không có ý nghĩa.
ewwhite

Câu trả lời:


4

Nếu bạn chỉ sử dụng InnoDB cho tất cả các bảng và đặt innodb_flush_log_at_trx_committhành:

  • 1 (nội dung của bộ đệm nhật ký InnoDB được ghi ra tệp nhật ký tại mỗi lần giao dịch và tệp nhật ký được xóa vào đĩa) hoặc,
  • 2 (nội dung của bộ đệm nhật ký InnoDB được ghi vào tệp nhật ký sau mỗi lần giao dịch và tệp nhật ký được xóa vào đĩa khoảng một lần mỗi giây),

sau đó bạn không cần BẢNG XÓA trước khi thực hiện ảnh chụp nhanh, chỉ cần chạy ảnh chụp nhanh ZFS trực tiếp. InnoDB có thể khôi phục dữ liệu từ nhật ký cam kết giao dịch mà không mất dữ liệu.

Tham chiếu: https://dev.mysql.com/doc/refman/5.5/en/innodb-parameter.html#sysvar_innodb_flush_log_at_trx_commit


Với từ điển dữ liệu được giới thiệu trong MySQL 8, ngay cả các hoạt động DDL (sửa đổi lược đồ) giờ cũng là nguyên tử. Trước đó, các hoạt động DDL trong ảnh chụp nhanh hệ thống tệp có thể cho kết quả được cam kết một phần (tức là bị hỏng).
bernie

13

Bạn cần khóa cơ sở dữ liệu đầy đủ để sao lưu (hầu hết) cơ sở dữ liệu một cách nhất quán.

Hướng dẫn sử dụng https://dev.mysql.com/doc/refman/5.5/en/backup-methods.html cho biết BẢNG BIỂU TƯỢNG VỚI READ LOCK là chính xác cho các ảnh chụp nhanh ZFS cụ thể.

Tạo bản sao lưu bằng ảnh chụp hệ thống tệp

Nếu bạn đang sử dụng hệ thống tệp Veritas, bạn có thể tạo bản sao lưu như thế này:

  1. Từ một chương trình khách hàng, thực hiện FLUSH TABLES WITH READ LOCK.
  2. Từ một shell khác, thực hiện vxfssnapshot snap.
  3. Từ khách hàng đầu tiên, thực hiện UNLOCK TABLES.
  4. Sao chép tập tin từ ảnh chụp nhanh.
  5. Ngắt kết quả chụp nhanh.

Khả năng chụp nhanh tương tự có thể có sẵn trong các hệ thống tệp khác, chẳng hạn như LVM hoặc ZFS.

Nó là loại vô lý mà họ bỏ qua thực tế là bạn cần FLUSH TABLES table_a, table_b, table_c FOR EXPORTcho InnoDB từ hướng dẫn này. Thật ngu ngốc khi phải chỉ định từng bảng như thế. Nhưng như EEAA nói, bạn có thể tạo một danh sách các bảng khi bạn bắt đầu sao lưu khá dễ dàng.

Đối với việc giữ khóa, bạn phải giữ kết nối db hoạt động trong khi thực hiện ảnh chụp nhanh

Nói chung, tôi sẽ sử dụng một cái gì đó như Perl hoặc một ngôn ngữ lập trình khác có thể kết nối, khóa db và trong khi duy trì kết nối db, hãy chụp nhanh, sau đó mở khóa và ngắt kết nối. Nó không phức tạp. Tôi muốn đặt cược rằng có những công cụ hiện có đã làm được điều này nhưng viết một công cụ thì dễ.

Tôi nói dễ, không phức tạp, v.v. vài lần. Tôi giả sử bạn có một số lập trình cơ bản hoặc kỹ năng viết kịch bản tốt.


Tôi đã hy vọng giữ một kịch bản đơn giản về mặt khái niệm như vậy trong Bash, nhưng việc bạn chuyển đổi ngôn ngữ đúng sẽ giúp việc này dễ dàng hơn nhiều. Tôi có thể đang đọc câu trả lời của bạn sai, nhưng có vẻ như bạn đang nói rằng tôi cần phải thực thi cả hai FLUSH TABLES WITH READ LOCKvà sau đó FLUSH TABLES...FOR EXPORT, trong khi việc đọc hướng dẫn sử dụng MySQL của tôi chỉ nói một điều cần thiết.
Andy Shulman

Xin lỗi tôi đã không rõ ràng. Tôi chỉ đang làm theo hướng dẫn và nó nói hai điều khác nhau. Tôi đoán bạn là chính xác và chỉ cần sau này. Nhưng tất cả các bảng nên được khóa trong một lệnh.
Ryan Babchishin

1
Do tài liệu không rõ ràng, toàn bộ cơ sở dữ liệu cần phải được khóa và phải duy trì kết nối DB trong khi chụp nhanh, có vẻ như chỉ cần tắt DB, sao lưu và khởi động lại nó
Andrew Henle

2
@andrew thở dài ... Tôi hiểu. Nhưng điều đó sẽ chậm, khiến các kết nối bị rớt / hỏng và tôi đã thấy nó khiến cơ sở dữ liệu không thể sao lưu đúng cách (không tốt cho tự động hóa). Sẽ là tốt để có được một câu trả lời dứt khoát từ mysql / Oracle. Họ phải có một danh sách gửi thư.
Ryan Babchishin

7

Tôi đã tách ra và điều chỉnh một kịch bản đơn giản về mặt khái niệm trong Bash mà tôi đã tìm thấy trong một bài đăng khác về Server Fault của Tobia . Nó sẽ giúp bạn có khoảng 90% đường đến đó.

mysql_locked=/var/run/mysql_locked

# flush & lock MySQL, touch mysql_locked, and wait until it is removed
mysql -hhost -uuser -ppassword -NB <<-EOF &
    flush tables with read lock;
    delimiter ;;
    system touch $mysql_locked
    system while test -e $mysql_locked; do sleep 1; done
    exit
EOF

# wait for the preceding command to touch mysql_locked
while ! test -e $mysql_locked; do sleep 1; done

# take a snapshot of the filesystem, while MySQL is being held locked
zfs snapshot zpool/$dataset@$(date +"%Y-%m-%d_%H:%M")

# unlock MySQL
rm -f $mysql_locked

Ở đây, mysqllệnh bạn sử dụng được chạy trong nền và chạm vào một tệp. Nó chờ trong nền để tập tin biến mất trước khi thoát và do đó mở khóa các bảng. Trong khi đó, tập lệnh chính đợi cho đến khi tập tin tồn tại, sau đó tạo ảnh chụp nhanh và xóa tập tin.

Tệp được chỉ ra bởi $mysql_lockednhu cầu có thể truy cập được cho cả hai máy, bạn có thể dễ dàng thực hiện đủ vì cả hai đều có thể truy cập vào một tập dữ liệu chung (mặc dù chúng có thể sử dụng các đường dẫn khác nhau và bạn nên tính đến điều này).


Tôi không biết kịch bản MySQL, vì vậy đây có thể là một ý tưởng ngớ ngẩn, nhưng bạn không thể thực hiện system zfs snapshot...bên trong kịch bản chính? Hay là snap-shaping phải chạy trong một quy trình riêng biệt?
TripeHound

@Tripehound cả hai điều cần phải xảy ra song song bằng cách nào đó
Ryan Babchishin

@RyanBabchishin Tôi nghĩ rằng anh ấy đúng, thực sự. Các SYSTEMlệnh chạy điều tại địa phương. Nếu tôi chạy ứng dụng khách mysql trên hộp FreeBSD và thực thi LOCK; SYSTEM zfs snapshot; UNLOCK, có vẻ như nó sẽ hoạt động.
Andy Shulman

@Andy Tôi chỉ nói họ cần xảy ra song song. Không quan trọng bạn đi về nó như thế nào.
Ryan Babchishin

2

Bạn cần BẢNG XÓA VỚI ĐỌC KHÓA cho myisam vì nó không ghi nhật ký.

Bạn thực sự không cần bất cứ điều gì cho innodb, IMO, bởi vì nó đang viết nhật ký. Dù sao thì nó cũng sẽ nhất quán, chỉ cần tự động quay lại tạp chí nếu có bất cứ điều gì xảy ra ở thời điểm nguyên tử mà bạn chụp.

Nếu bạn muốn tính nhất quán ở cấp ứng dụng, ứng dụng của bạn nên sử dụng các giao dịch. Nếu ứng dụng của bạn sử dụng các giao dịch và innodb, bất kỳ ảnh chụp nhanh nào cũng sẽ nhất quán hỏi cách tự động lên cấp ứng dụng.


2

Đây là giải pháp của tôi về cách tạo ảnh chụp nhanh ZFS trong khi giữ khóa:

mysql << EOF
    FLUSH TABLES WITH READ LOCK;
    system zfs snapshot data/db@snapname
    UNLOCK TABLES;
EOF
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.