1. 程式人生 > 實用技巧 >MySQL - 更新表中的資料記錄

MySQL - 更新表中的資料記錄

技術標籤:資料庫mysqlsqlnosql

資料備份的重要性

1、在生產環境中,資料的安全性至關重要
2、任何資料的丟失都可能產生嚴重的後果
3、造成資料丟失的原因
4、程式錯誤
5、人為操作錯誤
6、運算錯誤
7、磁碟故障
8、災難(如火災,地震)和盜竊

資料庫備份的分類

從物理與邏輯的角度,備份可分為
1、物理備份:對資料庫作業系統的物理檔案(如資料檔案、日誌檔案等)的備份
物理備份方法
冷備份(離線備份):是在關閉資料庫的時候進行的
熱備份(聯機備份):資料庫處於執行狀態,依賴於資料庫的日誌檔案
溫備份:資料庫鎖定表格(不可寫入但可讀)的狀態下進行備份操作
2、邏輯備份:對資料庫邏輯元件(如:表等資料庫物件)的備份

從資料庫的備份策略角度,備份可分為
1、完全備份:每次對資料庫進行完整的備份
2、差異備份:備份自從上次完全備份之後被修改過的檔案
3、增量備份:只有在上次完全備份或者增量備份後被修改的檔案才會被備份

MySQL完全備份與恢復

常見的備份方法
物理冷備
備份時資料庫處於關閉狀態,直接打包資料庫檔案
備份速度快,恢復時也是最簡單的
專業備份工具mysqldump或mysqlhotcopy
mysqldump常用的邏輯備份工具
mysqlhotcopy僅擁有備份MyISAM和ARCHIVE表
啟用二進位制日誌進行增量備份
進行增量備份,需要重新整理二進位制日誌
第三方工具備份
免費的MySQL熱備份軟體Percona XtraBackup

MySQL完全備份簡介

1、是對整個資料庫、資料庫結構和檔案結構的備份
2、儲存的是備份完成時刻的資料庫
3、是差異備份與增量備份的基礎
4、每次對資料進行完整的備份,完全備份是增量備份的基礎,完全備份儲存的是備份完成時刻的資料庫
5、優點:
備份與恢復操作簡單方便
6、缺點
資料存在大量的重複
佔用大量的備份空間
備份與恢復時間長

資料庫完全備份分類

1、物理冷備份與恢復
關閉MySQL資料庫
使用tar命令直接打包資料庫資料夾
直接替換現有MySQL目錄即可
2、mysqldump備份與恢復
MySQL自帶的備份工具,可方便實現對MySQL的備份
可以將指定的庫、表匯出為SQL指令碼(.sql結尾)

使用命令MySQL匯入備份的資料

物理冷備份與恢復步驟

1、在MySQL中先建立test庫,再建立aa表,寫入一行記錄(用於驗證)
在這裡插入圖片描述
2、先關閉資料庫服務,再打包備份

[[email protected] ~]# systemctl stop mysqld
[[email protected] ~]# mkdir /backup
[[email protected] ~]# tar zcf /backup/mysql_all-$(date +%F).tar.gz /usr/local/mysql/data
[[email protected] ~]# cd /backup
[[email protected] backup]# ll
總用量 1376
-rw-r--r--. 1 root root 1405224 1023 20:30 mysql_all-2020-10-23.tar.gz

3、將原來的資料移走到備份資料夾中,解壓剛才備份的tar包到/restore目錄下,再移動到mysql服務的資料夾中

[[email protected] ~]# mkdir bak
[[email protected] ~]# mv /usr/local/mysql/data/ /bak ###將資料庫的檔案移動至/bak資料夾中
[[email protected] ~]# mkdir restore
[[email protected] ~]# tar zxf /backup/mysql_all-2020-10-23.tar.gz -C restore
[[email protected] ~]# mv restore/usr/local/mysql/data/ /usr/local/mysql/ ###將之前備份的檔案移動至mysql服務的資料夾中

4、重啟mysql服務,登入mysql,檢視資料是否恢復

[[email protected] ~]# systemctl restart mysqld

在這裡插入圖片描述

mysqldump備份和恢復

mysqldump -u root -p --all-databses > all-data-KaTeX parse error: Expected 'EOF', got '#' at position 87: …auth-mysql.sql #̲##備份auth和mysql庫…(data +%F).sql ###備份auth資料庫
mysqldump -u root -p mysql user > mysql-user-$(date +%F).sql ###備份mysql的user表
mysqldump -u root -p -d mysql user > /tmp/desc-mysql-user.sql ###備份mysql庫user表的結構

1、方法一

[[email protected] ~]# mysqldump -u root -p test > test-$(date +%F).sql
mysql> drop database test;
mysql> create database test2; ###建立空庫
[[email protected] ~]# mysql -u root -p test2 < test-2020-12-25.sql

2、方法二

[[email protected] ~]# mysqldump -u root -p test > test-$(date +%F).sql
mysql> drop database test;
mysql> create database test2;
mysql> use test2;
mysql> source /root/test-2020-12-25.sql;

MySQL增量備份與恢復

1、使用mysqldump進行完全備份存在的問題
備份資料中有重複資料
備份時間與恢復時間過長
2、MySQL增量備份是自上一次備份後增加/變化的檔案或者內容
3、特點
沒有重複資料,備份量不大,時間短
恢復需要上次完全備份及完全備份之後所有的增量備份才能恢復,而且要對所有增量備份進行逐個反推恢復

4、MySQL沒有提供直接的增量備份方法
可通過MySQL提供的二進位制日誌間接實現增量備份
5、MySQL二進位制日誌對備份的意義
二進位制日誌儲存了所有更新或者可能更新資料庫的操作
二進位制日誌在啟動MySQL伺服器後開始記錄,並在檔案達到max_binlog_size所設定的大小或者接收到flush logs命令後重新建立新的日誌檔案
只需定時執行flush logs方法重新建立新的日誌,生成二進位制檔案序列,並及時把這些日誌儲存到安全的地方就完成了一個時間段的增量備份

MySQL資料庫增量恢復

1、一般恢復
將所有備份的二進位制日誌內容全部恢復
2、斷點恢復
基於位置恢復
資料庫在某一時間點可能既有錯誤的操作也有正確的操作
可以基於精準的位置跳過錯誤的操作
基於時間點恢復
跳過某個發生錯誤的時間點實現資料恢復

增量恢復的方法

1、一般恢復
mysqlbinlog [–no-defaults] 增量備份檔案 | mysql -u 使用者名稱 -p
2、基於位置的恢復
恢復資料到指定位置(到錯誤操作前的最後一次正確操作)
mysqlbinlog --stop-position=‘操作id’ 二進位制日誌 | mysql -u 使用者名稱 -p密碼
從指定的位置開始恢復資料(跳過錯誤操作後的第一次正確操作)
mysqlbinlog --start-position=‘操作id’ 二進位制日誌 | mysql -u 使用者名稱 -p密碼
3、基於時間點恢復
跳過某個發生錯誤的時間點實現資料恢復
恢復資料到指定時間(停止錯誤操作的時間)
mysqlbinlog --stop-datetime=‘錯誤時間’ 二進位制日誌 | mysql -u 使用者名稱 -p密碼
從指定的位置開始恢復資料(跳過錯誤操作後的第一次正確操作)
mysqlbinlog --start-datetime=‘正確操作時間’ 二進位制日誌 | mysql -u 使用者名稱 -p密碼

時間點恢復:

[[email protected] ~]# mkdir -p /bak_sql
[[email protected] ~]# mysqldump -uroot -p test2 > /bak_sql/test2-$(date +%F).sql; ###完整備份

[[email protected] ~]# vi /etc/my.cnf
[mysqld]
log_bin=/usr/local/mysql/data/mysql_bin ###開啟增量備份

[[email protected] ~]# systemctl restart mysqld

[[email protected] ~]# mysqladmin -uroot -p flush-logs ###將二進位制日誌更新,產生新的日誌檔案
[[email protected] ~]# cd /usr/local/mysql/data/
[[email protected] data]# ll ###查詢增量備份結果

[[email protected] ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql_bin.000002 ###查詢該二進位制日誌內容是否正確

mysql> insert into aa values(4,'sisi',90); ###正確操作
mysql> delete from aa where name='zhangsan'; ###錯誤操作
mysql> insert into aa values(5,'haha',89); ###正確操作
mysql> select * from aa;
+----+--------+-------+
| id | name   | score |
+----+--------+-------+
|  1 | lisi   | 88    |
|  3 | wangwu | 78    |
|  4 | sisi   | 90    |
|  5 | haha   | 89    |
+----+--------+-------+
4 rows in set (0.01 sec)

[[email protected] ~]# mysqladmin -u root -p flush-logs; ###將二進位制日誌更新,產生新的日誌檔案
[[email protected] ~]# cd /usr/local/mysql/data/
[[email protected] data]# ll ###查詢增量備份結果
[[email protected] ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql_bin.000003 ###查詢該二進位制日誌內容是否正確

###還原時間點的步驟
mysql> use test2;
mysql> drop table aa; ###先刪掉壞的那張表
[[email protected] ~]# mysql -u root -p test2 < /opt/bak_sql/test2-2020-12-25.sql ###還原完全備份的資料庫

[[email protected] ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql_bin.000002 ###查詢該二進位制日誌內容
# at 613
#201225  0:55:25 server id 1  end_log_pos 665 CRC32 0xa674c8df  Delete_rows: table id 219 flags: STMT_END_F
### DELETE FROM `test2`.`aa`
### WHERE
###   @1=2
###   @2='zhangsan'
###   @3='60'
# at 665
#201225  0:55:25 server id 1  end_log_pos 696 CRC32 0x297a966a  Xid = 14
COMMIT/*!*/;
# at 696
#201225  0:55:48 server id 1  end_log_pos 761 CRC32 0x11834792  Anonymous_GTID  last_committed=2        sequence_number=3       rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 761
#201225  0:55:48 server id 1  end_log_pos 834 CRC32 0x28de3d38  Query   thread_id=4     exec_time=0     error_code=0
SET TIMESTAMP=1603526148/*!*/;
BEGIN
/*!*/;
# at 834
#201225  0:55:48 server id 1  end_log_pos 886 CRC32 0xa67e20b9  Table_map: `test2`.`aa` mapped to number 219
# at 886
#201225  0:55:48 server id 1  end_log_pos 934 CRC32 0x8a2c0765  Write_rows: table id 219 flags: STMT_END_F
### INSERT INTO `test2`.`aa`
### SET
###   @1=5
###   @2='haha'
###   @3='89'

[[email protected] ~]# mysqlbinlog --no-defaults --stop-datetime='2020-12-25  0:55:25' /usr/local/mysql/data/mysql_bin.000002 | mysql -u root -p ###停止錯誤的時間

[[email protected] ~]# mysqlbinlog --no-defaults --start-datetime='2020-12-25  0:55:48' /usr/local/mysql/data/mysql_bin.000002 | mysql -u root -p ###開始正確的時間

mysql> select * from aa; ###檢視是否復原
+----+----------+-------+
| id | name     | score |
+----+----------+-------+
|  1 | lisi     | 88    |
|  2 | zhangsan | 60    |
|  3 | wangwu   | 78    |
|  4 | sisi     | 90    |
|  5 | haha     | 89    |
+----+----------+-------+
5 rows in set (0.00 sec)

位置點恢復:

mysql> use test2;
mysql> delete from aa where name='lisi'; ###誤操作
mysql> delete from aa where name='haha'; ###誤操作

[[email protected] ~]# mysqlbinlog --no-defaults --base64-output=decode-rows -v /usr/local/mysql/data/mysql_bin.000003 ###查詢該二進位制日誌內容
...省略內容
# at 2168
#201225  1:12:20 server id 1  end_log_pos 2220 CRC32 0x5a192cfd         Table_map: `test2`.`aa` mapped to number 221
# at 2220
#201225  1:12:20 server id 1  end_log_pos 2268 CRC32 0x30f35bdf         Delete_rows: table id 221 flags: STMT_END_F
### DELETE FROM `test2`.`aa`
### WHERE
###   @1=1
###   @2='lisi'
###   @3='88'
# at 2268
#201225  1:12:20 server id 1  end_log_pos 2299 CRC32 0xe8fa9bd8         Xid = 123
COMMIT/*!*/;
# at 2299
#201225  1:12:26 server id 1  end_log_pos 2364 CRC32 0xfa901848         Anonymous_GTID  last_committed=9        sequence_number=10  rbr_only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 2364
#201225 1:12:26 server id 1  end_log_pos 2437 CRC32 0x04379db1         Query   thread_id=12    exec_time=0     error_code=0
SET TIMESTAMP=1603527986/*!*/;
BEGIN
/*!*/;
# at 2437
#201225  1:12:26 server id 1  end_log_pos 2489 CRC32 0xa0c3b6c1         Table_map: `test2`.`aa` mapped to number 221
# at 2489
#201225  1:12:26 server id 1  end_log_pos 2537 CRC32 0xd7509926         Delete_rows: table id 221 flags: STMT_END_F
### DELETE FROM `test2`.`aa`
### WHERE
###   @1=5
###   @2='haha'
###   @3='89'
# at 2537
#201225  1:12:26 server id 1  end_log_pos 2568 CRC32 0xb7b17eee         Xid = 124
...省略內容

[[email protected] ~]# mysqlbinlog --no-defaults --stop-position='2168' /usr/local/mysql/data/mysql_bin.000003 | mysql -u root -p ###上一次操作正確的位置點停止
[[email protected] ~]# mysqlbinlog --no-defaults --start-position='2537' /usr/local/mysql/data/mysql_bin.000003 | mysql -u root -p ###下一次操作正確的位置點開始

mysql> select * from aa;
+----+----------+-------+
| id | name     | score |
+----+----------+-------+
|  1 | lisi     | 88    |
|  2 | zhangsan | 60    |
|  3 | wangwu   | 78    |
|  4 | sisi     | 90    |
|  5 | haha     | 89    |
+----+----------+-------+
5 rows in set (0.00 sec)