MariaDB
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> MariaDB

Sử dụng MariaDB Flashback trên MySQL Server

MariaDB đã giới thiệu một tính năng rất hay có tên là Flashback. Flashback là một tính năng cho phép các phiên bản, cơ sở dữ liệu hoặc bảng được quay trở lại ảnh chụp nhanh cũ. Theo truyền thống, để thực hiện khôi phục tại điểm trong thời gian (PITR), người ta sẽ khôi phục cơ sở dữ liệu từ bản sao lưu và phát lại các bản ghi nhị phân để chuyển tiếp trạng thái cơ sở dữ liệu tại một thời điểm hoặc vị trí nhất định.

Với Flashback, cơ sở dữ liệu có thể được quay trở lại một thời điểm trong quá khứ, nhanh hơn nếu chúng ta chỉ muốn xem quá khứ vừa xảy ra cách đây không lâu. Đôi khi, sử dụng hồi tưởng có thể không hiệu quả nếu bạn muốn xem ảnh chụp nhanh dữ liệu rất cũ của mình so với ngày và giờ hiện tại. Khôi phục từ một nô lệ bị trì hoãn hoặc từ một bản sao lưu cộng với phát lại nhật ký nhị phân có thể là những lựa chọn tốt hơn.

Tính năng này chỉ có sẵn trong gói ứng dụng khách MariaDB, nhưng điều đó không có nghĩa là chúng tôi không thể sử dụng nó với các máy chủ MySQL của mình. Bài đăng trên blog này giới thiệu cách chúng ta có thể sử dụng tính năng tuyệt vời này trên máy chủ MySQL.

Yêu cầu về hồi tưởng MariaDB

Đối với những người muốn sử dụng tính năng hồi tưởng MariaDB trên MySQL, về cơ bản chúng ta có thể làm như sau:

  1. Bật nhật ký nhị phân với cài đặt sau:
    1. binlog_format =ROW (mặc định kể từ MySQL 5.7.7).
    2. binlog_row_image =FULL (mặc định kể từ MySQL 5.6).
  2. Sử dụng tiện ích msqlbinlog từ mọi cài đặt MariaDB 10.2.4 trở lên.
  3. Flashback hiện chỉ được hỗ trợ qua các câu lệnh DML (CHÈN, XÓA, CẬP NHẬT). Phiên bản sắp tới của MariaDB sẽ bổ sung hỗ trợ cho các câu lệnh hồi tưởng qua DDL (DROP, TRUNCATE, ALTER, v.v.) bằng cách sao chép hoặc di chuyển bảng hiện tại sang cơ sở dữ liệu dành riêng và ẩn, sau đó sao chép hoặc di chuyển trở lại khi sử dụng hồi tưởng.

Hồi tưởng đạt được bằng cách tận dụng sự hỗ trợ hiện có cho các bản ghi nhị phân định dạng hình ảnh đầy đủ, do đó nó hỗ trợ tất cả các công cụ lưu trữ. Lưu ý rằng các sự kiện hồi tưởng sẽ được lưu trữ trong bộ nhớ. Do đó, bạn nên đảm bảo máy chủ của mình có đủ bộ nhớ cho tính năng này.

MariaDB Flashback hoạt động như thế nào?

Tiện ích mysqlbinlog của MariaDB đi kèm với hai tùy chọn bổ sung cho mục đích này:

  • - B, --flashback - Tính năng hồi tưởng có thể khôi phục dữ liệu đã cam kết của bạn đến một thời điểm đặc biệt.
  • - T, --table =[name] - Chỉ liệt kê các mục nhập cho bảng này (chỉ nhật ký cục bộ).

Bằng cách so sánh đầu ra mysqlbinlog có và không có cờ --flashback, chúng ta có thể dễ dàng hiểu cách hoạt động của nó. Hãy xem xét câu lệnh sau được thực thi trên máy chủ MariaDB:

MariaDB> DELETE FROM sbtest.sbtest1 WHERE id = 1;

Không có cờ hồi tưởng, chúng ta sẽ thấy sự kiện DELETE binlog thực tế:

$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000003

...
# at 453196541
#200227 12:58:18 server id 37001  end_log_pos 453196766 CRC32 0xdaa248ed Delete_rows: table id 238 flags: STMT_END_F

BINLOG '
6rxXXhOJkAAAQwAAAP06AxsAAO4AAAAAAAEABnNidGVzdAAHc2J0ZXN0MQAEAwP+/gTu4P7wAAEB
AAID/P8AFuAQfA==
6rxXXiCJkAAA4QAAAN47AxsAAO4AAAAAAAEAAgAE/wABAAAAVJ4HAHcAODM4Njg2NDE5MTItMjg3
NzM5NzI4MzctNjA3MzYxMjA0ODYtNzUxNjI2NTk5MDYtMjc1NjM1MjY0OTQtMjAzODE4ODc0MDQt
NDE1NzY0MjIyNDEtOTM0MjY3OTM5NjQtNTY0MDUwNjUxMDItMzM1MTg0MzIzMzA7Njc4NDc5Njcz
NzctNDgwMDA5NjMzMjItNjI2MDQ3ODUzMDEtOTE0MTU0OTE4OTgtOTY5MjY1MjAyOTHtSKLa
'/*!*/;

### DELETE FROM `sbtest`.`sbtest1`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=499284 /* INT meta=0 nullable=0 is_null=0 */
###   @3='83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='67847967377-48000963322-62604785301-91415491898-96926520291' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...

Bằng cách mở rộng lệnh mysqlbinlog ở trên với --flashback, chúng ta có thể thấy sự kiện DELETE được chuyển đổi thành sự kiện INSERT và tương tự như các mệnh đề WHERE và SET tương ứng:

$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000003 \
--flashback

...
BINLOG '
6rxXXhOJkAAAQwAAAP06AxsAAO4AAAAAAAEABnNidGVzdAAHc2J0ZXN0MQAEAwP+/gTu4P7wAAEB
AAID/P8AFuAQfA==
6rxXXh6JkAAA4QAAAN47AxsAAO4AAAAAAAEAAgAE/wABAAAAVJ4HAHcAODM4Njg2NDE5MTItMjg3
NzM5NzI4MzctNjA3MzYxMjA0ODYtNzUxNjI2NTk5MDYtMjc1NjM1MjY0OTQtMjAzODE4ODc0MDQt
NDE1NzY0MjIyNDEtOTM0MjY3OTM5NjQtNTY0MDUwNjUxMDItMzM1MTg0MzIzMzA7Njc4NDc5Njcz
NzctNDgwMDA5NjMzMjItNjI2MDQ3ODUzMDEtOTE0MTU0OTE4OTgtOTY5MjY1MjAyOTHtSKLa
'/*!*/;

### INSERT INTO `sbtest`.`sbtest1`
### SET
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=499284 /* INT meta=0 nullable=0 is_null=0 */
###   @3='83868641912-28773972837-60736120486-75162659906-27563526494-20381887404-41576422241-93426793964-56405065102-33518432330' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='67847967377-48000963322-62604785301-91415491898-96926520291' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...

Trong sao chép dựa trên hàng (binlog_format =ROW), mỗi sự kiện thay đổi hàng chứa hai hình ảnh, một hình ảnh “trước” (ngoại trừ CHÈN) có các cột được khớp với nhau khi tìm kiếm hàng được cập nhật, và hình ảnh “sau” (ngoại trừ XÓA) chứa các thay đổi. Với binlog_row_image =FULL, MariaDB ghi lại các hàng đầy đủ (nghĩa là tất cả các cột) cho cả hình ảnh trước và sau.

Ví dụ sau cho thấy các sự kiện nhật ký nhị phân cho CẬP NHẬT. Hãy xem xét câu lệnh sau được thực thi trên máy chủ MariaDB:

MariaDB> UPDATE sbtest.sbtest1 SET k = 0 WHERE id = 5;

Khi nhìn vào sự kiện binlog cho câu lệnh trên, chúng ta sẽ thấy như sau:

$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 5 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000001 

...
### UPDATE `sbtest`.`sbtest1`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=499813 /* INT meta=0 nullable=0 is_null=0 */
###   @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=0 /* INT meta=0 nullable=0 is_null=0 */
###   @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
# Number of rows: 1
...

Với cờ --flashback, hình ảnh "trước" được hoán đổi với hình ảnh "sau" của hàng hiện có:

$ mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 5 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000001 \
 --flashback

...
### UPDATE `sbtest`.`sbtest1`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=0 /* INT meta=0 nullable=0 is_null=0 */
###   @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
### SET
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=499813 /* INT meta=0 nullable=0 is_null=0 */
###   @3='44257470806-17967007152-32809666989-26174672567-29883439075-95767161284-94957565003-35708767253-53935174705-16168070783' /* STRING(480) meta=61152 nullable=0 is_null=0 */
###   @4='34551750492-67990399350-81179284955-79299808058-21257255869' /* STRING(240) meta=65264 nullable=0 is_null=0 */
...

Sau đó, chúng tôi có thể chuyển hướng đầu ra hồi tưởng đến máy khách MySQL, do đó quay trở lại cơ sở dữ liệu hoặc bảng về thời điểm mà chúng tôi muốn. Các ví dụ khác được hiển thị trong các phần tiếp theo.

MariaDB có một trang cơ sở kiến ​​thức dành riêng cho tính năng này. Xem trang cơ sở kiến ​​thức về MariaDB Flashback.

MariaDB Flashback Với MySQL

Để có khả năng hồi tưởng cho MySQL, người ta phải làm như sau:

  • Sao chép tiện ích mysqlbinlog từ bất kỳ máy chủ MariaDB nào (10.2.4 trở lên).
  • Tắt MySQL GTID trước khi áp dụng tệp SQL hồi tưởng. Các biến toàn cục gtid_mode và execute_gtid_consistency có thể được đặt trong thời gian chạy kể từ MySQL 5.7.5.

Giả sử chúng ta đang có cấu trúc liên kết sao chép MySQL 8.0 đơn giản sau:

Trong ví dụ này, chúng tôi đã sao chép tiện ích mysqlbinlog từ MariaDB 10.4 mới nhất trên một trong các nô lệ MySQL 8.0 (slave2) của chúng tôi:

(mariadb-server)$ scp /bin/mysqlbinlog [email protected]:/root/
(slave2-mysql8)$ ls -l /root/mysqlbinlog
-rwxr-xr-x. 1 root root 4259504 Feb 27 13:44 /root/mysqlbinlog

Tiện ích mysqlbinlog của MariaDB của chúng tôi hiện được đặt tại / root / mysqlbinlog trên slave2. Trên MySQL master, chúng tôi đã thực thi câu lệnh tai hại sau:

mysql> DELETE FROM sbtest1 WHERE id BETWEEN 5 AND 100;
Query OK, 96 rows affected (0.01 sec)

96 hàng đã bị xóa trong câu lệnh trên. Chờ một vài giây để các sự kiện lặp lại từ chính đến tất cả các nô lệ trước khi chúng tôi có thể cố gắng tìm vị trí binlog của sự kiện thảm hại trên máy chủ nô lệ. Bước đầu tiên là truy xuất tất cả nhật ký nhị phân trên máy chủ đó:

mysql> SHOW BINARY LOGS;
+---------------+-----------+-----------+
| Log_name      | File_size | Encrypted |
+---------------+-----------+-----------+
| binlog.000001 |       850 |        No |
| binlog.000002 |     18796 |        No |
+---------------+-----------+-----------+

Sự kiện thảm khốc của chúng ta sẽ tồn tại bên trong binlog.000002, nhật ký nhị phân mới nhất trong máy chủ này. Sau đó, chúng tôi có thể sử dụng tiện ích mysqlbinlog của MariaDB để truy xuất tất cả các sự kiện binlog cho bảng sbtest1 kể từ 10 phút trước:

(slave2-mysql8)$ /root/mysqlbinlog -vv \
--start-datetime="$(date '+%F %T' -d 'now - 10 minutes')" \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002

...
# at 195
#200228 15:09:45 server id 37001  end_log_pos 281 CRC32 0x99547474 Ignorable
# Ignorable event type 33 (MySQL Gtid)
# at 281
#200228 15:09:45 server id 37001  end_log_pos 353 CRC32 0x8b12bd3c Query thread_id=19 exec_time=0 error_code=0
SET TIMESTAMP=1582902585/*!*/;
SET @@session.pseudo_thread_id=19/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1, @@session.check_constraint_checks=1/*!*/;
SET @@session.sql_mode=524288/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
SET @@session.character_set_client=255,@@session.collation_connection=255,@@session.collation_server=255/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;

BEGIN
/*!*/;
# at 353
#200228 15:09:45 server id 37001  end_log_pos 420 CRC32 0xe0e44a1b Table_map: `sbtest`.`sbtest1` mapped to number 92

# at 420
# at 8625
# at 16830
#200228 15:09:45 server id 37001  end_log_pos 8625 CRC32 0x99b1a8fc Delete_rows: table id 92
#200228 15:09:45 server id 37001  end_log_pos 16830 CRC32 0x89496a07 Delete_rows: table id 92
#200228 15:09:45 server id 37001  end_log_pos 18765 CRC32 0x302413b2 Delete_rows: table id 92 flags: STMT_END_F

Để dễ dàng tra cứu số vị trí binlog, hãy chú ý đến các dòng bắt đầu bằng "# at". Từ các dòng trên, chúng ta có thể thấy sự kiện DELETE đang xảy ra ở vị trí 281 bên trong binlog.000002 (bắt đầu từ "# tại 281"). Chúng tôi cũng có thể truy xuất các sự kiện binlog trực tiếp bên trong máy chủ MySQL:

mysql> SHOW BINLOG EVENTS IN 'binlog.000002';
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+
| Log_name      | Pos   | Event_type     | Server_id | End_log_pos | Info                                                              |
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+
| binlog.000002 |     4 | Format_desc    |     37003 | 124         | Server ver: 8.0.19, Binlog ver: 4                                 |
| binlog.000002 |   124 | Previous_gtids |     37003 | 195         | 0d98d975-59f8-11ea-bd30-525400261060:1                            |
| binlog.000002 |   195 | Gtid           |     37001 | 281         | SET @@SESSION.GTID_NEXT= '0d98d975-59f8-11ea-bd30-525400261060:2' |
| binlog.000002 |   281 | Query          |     37001 | 353         | BEGIN                                                             |
| binlog.000002 |   353 | Table_map      |     37001 | 420         | table_id: 92 (sbtest.sbtest1)                                     |
| binlog.000002 |   420 | Delete_rows    |     37001 | 8625        | table_id: 92                                                      |
| binlog.000002 |  8625 | Delete_rows    |     37001 | 16830       | table_id: 92                                                      |
| binlog.000002 | 16830 | Delete_rows    |     37001 | 18765       | table_id: 92 flags: STMT_END_F                                    |
| binlog.000002 | 18765 | Xid            |     37001 | 18796       | COMMIT /* xid=171006 */                                           |
+---------------+-------+----------------+-----------+-------------+-------------------------------------------------------------------+

9 rows in set (0.00 sec)

Bây giờ chúng ta có thể xác nhận rằng vị trí 281 là nơi chúng ta muốn dữ liệu của mình trở lại. Sau đó, chúng tôi có thể sử dụng cờ --start-position để tạo các sự kiện hồi tưởng chính xác. Lưu ý rằng chúng tôi bỏ qua cờ "-vv" và thêm cờ --flashback:

(slave2-mysql8)$ /root/mysqlbinlog \
--start-position=281 \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002 \
--flashback > /root/flashback.binlog

Flashback.binlog chứa tất cả các sự kiện bắt buộc để hoàn tác tất cả các thay đổi đã xảy ra trên bảng sbtest1 trên máy chủ MySQL này. Vì đây là một nút nô lệ của một cụm sao chép, chúng ta phải phá vỡ bản sao trên nô lệ đã chọn (slave2) để sử dụng nó cho mục đích hồi tưởng. Để thực hiện việc này, chúng ta phải dừng sao chép trên nô lệ đã chọn, đặt MySQL GTID thành ON_PERMISSIVE và làm cho nô lệ có thể ghi:

mysql> STOP SLAVE; 
SET GLOBAL gtid_mode = ON_PERMISSIVE; 
SET GLOBAL enforce_gtid_consistency = OFF; 
SET GLOBAL read_only = OFF;

Tại thời điểm này, slave2 không phải là một phần của bản sao và cấu trúc liên kết của chúng tôi trông như thế này:

Nhập hồi tưởng qua ứng dụng mysql và chúng tôi không muốn thay đổi này được ghi lại trong nhật ký nhị phân MySQL:

(slave2-mysql8)$ mysql -uroot -p --init-command='SET sql_log_bin=0' sbtest < /root/flashback.binlog

Sau đó, chúng tôi có thể thấy tất cả các hàng đã xóa, như được chứng minh bằng câu lệnh sau:

mysql> SELECT COUNT(id) FROM sbtest1 WHERE id BETWEEN 5 and 100;
+-----------+
| COUNT(id) |
+-----------+
|        96 |
+-----------+
1 row in set (0.00 sec)

Sau đó, chúng tôi có thể tạo tệp kết xuất SQL cho bảng sbtest1 để chúng tôi tham khảo:

(slave2-mysql8)$ mysqldump -uroot -p --single-transaction sbtest sbtest1 > sbtest1_flashbacked.sql

Khi hoạt động hồi tưởng hoàn tất, chúng ta có thể tham gia lại nút phụ trở lại chuỗi sao chép. Nhưng trước hết, chúng ta phải đưa cơ sở dữ liệu trở lại trạng thái nhất quán, bằng cách phát lại tất cả các sự kiện bắt đầu từ vị trí mà chúng ta đã hồi tưởng. Đừng quên bỏ qua ghi nhật ký nhị phân vì chúng tôi không muốn "ghi" vào nô lệ và tự chịu rủi ro với các giao dịch sai lầm:

(slave2-mysql8)$ /root/mysqlbinlog \
--start-position=281 \
--database=sbtest \
--table=sbtest1 \
/var/lib/mysql/binlog.000002 | mysql -uroot -p --init-command='SET sql_log_bin=0' sbtest

Cuối cùng, chuẩn bị nút trở lại vai trò của nó như là nô lệ MySQL và bắt đầu sao chép:

mysql> SET GLOBAL read_only = ON;
SET GLOBAL enforce_gtid_consistency = ON; 
SET GLOBAL gtid_mode = ON; 
START SLAVE; 

Xác minh rằng nút phụ đang sao chép chính xác:

mysql> SHOW SLAVE STATUS\G
...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
...

Tại thời điểm này, chúng tôi đã tham gia lại nô lệ vào chuỗi sao chép và cấu trúc liên kết của chúng tôi hiện trở lại trạng thái ban đầu:

Cảm ơn nhóm MariaDB vì đã giới thiệu tính năng đáng kinh ngạc này!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Giải thích về toán tử MariaDB INTERSECT

  2. ClusterControl CMON HA cho tính khả dụng cao của cơ sở dữ liệu phân tán - Phần thứ hai (Thiết lập quyền truy cập GUI)

  3. MariaDB JSON_QUERY () Giải thích

  4. MariaDB JSON_ARRAY_INSERT () Giải thích

  5. Cách cài đặt, bảo mật và điều chỉnh hiệu suất của máy chủ cơ sở dữ liệu MariaDB