MySQL定時備份(全量備份+增量備份)

MySQL 定時備份

參考 zone7_ 的 實戰-MySQL定時備份系列文章

參考 zmcyu 的 mysql數據庫的完整備份、差異備份、增量備份

更多binlog的學習參考馬丁傳奇的 MySQL的binlog日志,這篇文章寫得認真詳細,如果看的認真的話,肯定能學的很好的。
如果查看binlog是出現語句加密的情況,參考 mysql row日志格式下 查看binlog sql語句

說明

產品上線后,數據非常非常重要,萬一哪天數據被誤刪,那么就gg了,準備跑路吧。
所以要對線上的數據庫定時做全量備份增量備份

增量備份的優點是沒有重復數據,備份量不大,時間短。但缺點也很明顯,需要建立在上次完全備份及完全備份之后所有的增量才能恢復。

MySQL沒有提供直接的增量備份方法,但是可以通過mysql二進制日志間接實現增量備份。二進制日志對備份的意義如下:

  • 二進制日志保存了所有更新或者可能更新數據的操作
  • 二進制日志在啟動MySQL服務器后開始記錄,并在文件達到所設大小或者收到flush logs 命令后重新創建新的日志文件
  • 只需定時執行flush logs 方法重新創建新的日志,生成二進制文件序列,并及時把這些文件保存到一個安全的地方,即完成了一個時間段的增量備份。

全量備份

mysqldump --lock-all-tables --flush-logs --master-data=2 -u root -p test > backup_sunday_1_PM.sql
  • 參數 --lock-all-tables

對于InnoDB將替換為 --single-transaction
該選項在導出數據之前提交一個 BEGIN SQL語句,BEGIN 不會阻塞任何應用程序且能保證導出時數據庫的一致性狀態。它只適用于事務表,例如 InnoDB 和 BDB。本選項和 --lock-tables 選項是互斥的,因為 LOCK TABLES 會使任何掛起的事務隱含提交。要想導出大表的話,應結合使用 --quick 選項。

  • 參數 --flush-logs,結束當前日志,生成并使用新日志文件

  • 參數 --master-data=2,該選項將會在輸出SQL中記錄下完全備份后新日志文件的名稱,用于日后恢復時參考,例如輸出的備份SQL文件中含有:CHANGE MASTER TO MASTER_LOG_FILE='MySQL-bin.000002', MASTER_LOG_POS=106;

  • 參數 test,該處的test表示數據庫test,如果想要將所有的數據庫備份,可以換成參數 --all-databases

  • 參數 --databases 指定多個數據庫

  • 參數 --quick-q,該選項在導出大表時很有用,它強制 MySQLdump 從服務器查詢取得記錄直接輸出而不是取得所有記錄后將它們緩存到內存中。

  • 參數 --ignore-table,忽略某個數據表,如 --ignore-table test.user 忽略數據庫test里的user表

  • 更多mysqldump 參數,請參考網址

全量備份腳本shell

#!/bin/bash
# mysql 數據庫全量備份# 用戶名、密碼、數據庫名
username="root"
password="tencns152"
dbName="goodthing"beginTime=`date +"%Y年%m月%d日 %H:%M:%S"`
# 備份目錄
bakDir=/home/mysql/backup
# 日志文件
logFile=/home/mysql/backup/bak.log
# 備份文件
nowDate=`date +%Y%m%d`
dumpFile="${dbName}_${nowDate}.sql"
gzDumpFile="${dbName}_${nowDate}.sql.tgz"cd $bakDir
# 全量備份(對所有數據庫備份,除了數據庫goodthing里的village表)
/usr/local/mysql/bin/mysqldump -u${username} -p${password} --quick --events --databases ${dbName} --ignore-table=goodthing.village --ignore-table=goodthing.area --flush-logs --delete-master-logs --single-transaction > $dumpFile
# 打包
/bin/tar -zvcf $gzDumpFile $dumpFile
/bin/rm $dumpFileendTime=`date +"%Y年%m月%d日 %H:%M:%S"`
echo 開始:$beginTime 結束:$endTime $gzDumpFile succ >> $logFile# 刪除所有增量備份
cd $bakDir/daily
/bin/rm -f *

這里全量備份只備份了一個數據庫,因為如果所有數據庫都備份的話,文件太大了。這里的取舍我也不是很清楚,畢竟自己還在學習階段,沒有實際的操作經驗。

增量備份

1. 檢查log_bin是否開啟

進入mysql命令行,執行 show variables like '%log_bin%'

mysql> show variables like '%log_bin%';
+---------------------------------+-------+
| Variable_name                   | Value |
+---------------------------------+-------+
| log_bin                         | OFF   |
| log_bin_basename                |       |
| log_bin_index                   |       |
| log_bin_trust_function_creators | OFF   |
| log_bin_use_v1_row_events       | OFF   |
| sql_log_bin                     | ON    |
+---------------------------------+-------+
6 rows in set (0.01 sec)

如上所示,log_bin 未開啟;如果log_bin開啟,則跳過第2步,直接進入第3步。

2. 開啟 log_bin,并重啟mysql

  • 編輯 mysql 的配置文件 vim /etc/my.cnf,在 mysqld 下面添加下面2條配置
[mysqld]
log-bin=/var/lib/mysql/mysql-bin
server_id=152

Tip1: 一定要加 server_id,否則會報錯。至于server_id的值,隨便設就可以。
Tip2: log_bin 中間可以下劃線_相連,也可以-減號相連。同理server_id也一樣。

  • 重啟mysql
service mysqld restart
  • 再次在mysql命令行中執行 show variables like '%log_bin%'
mysql> show variables like '%log_bin%';
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             |
| log_bin_basename                | /var/lib/mysql/mysql-bin       |
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF                            |
| log_bin_use_v1_row_events       | OFF                            |
| sql_log_bin                     | ON                             |
+---------------------------------+--------------------------------+
6 rows in set (0.01 sec)

3. 備份

  • 進入mysql命令行,執行 show master status;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      430 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

當前正在記錄日志的文件名是 mysql-bin.000003

  • 比如當前數據庫test的bk_user只有2條記錄
mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex  | age  |
+----+------+------+------+
|  1 | 小明 | 男   |   25 |
|  2 | 小紅 | 女   |   21 |
+----+------+------+------+
2 rows in set (0.00 sec)
  • 插入一條新的記錄
mysql> insert into test.bk_user(name, sex, age) values('小強', '男', 24);
Query OK, 1 row affected (0.02 sec)
mysql> select * from test.bk_user;
+----+------+-----+-----+
| id | name | sex | age |
+----+------+-----+-----+
|  1 | 小明 | 男  |  25 |
|  2 | 小紅 | 女  |  21 |
|  5 | 小強 | 男  |  24 |
+----+------+-----+-----+
3 rows in set (0.03 sec)
  • 執行命令mysqladmin -uroot -p密碼 flush-logs,生成并使用新的日志文件

再次查看當前使用的日志文件,已經變為 mysql-bin.000004 了。
mysql-bin.000003 則記錄著剛才執行的 insert 語句的日志。

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000004 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

到這里,其實已經完成了增量備份了。

恢復增量備份

  • 首先假裝誤刪數據庫記錄
mysql> delete from test.bk_user where id=4;
Query OK, 1 row affected (0.01 sec)mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex  | age  |
+----+------+------+------+
|  1 | 小明 | 男   |   25 |
|  2 | 小紅 | 女   |   21 |
+----+------+------+------+
2 rows in set (0.00 sec)
  • 從備份的日志文件mysql-bin.000003中恢復數據
[root@centos56 ~]# mysqlbinlog --no-defaults /var/lib/mysql/mysql-bin.000003 | mysql -uroot -p test
Enter password: 
ERROR 1032 (HY000) at line 36: Can't find record in 'bk_user'

如果你也遇到這個問題的話,不妨修改 /etc/my.cnf 配置試試。
我在server_id那一行下添加了 slave_skip_errors=1032 ,然后就執行成功了,不再報錯。

mysql> select * from test.bk_user;
+----+------+------+------+
| id | name | sex  | age  |
+----+------+------+------+
|  1 | 小明 | 男   |   25 |
|  2 | 小紅 | 女   |   21 |
|  5 | 小強 | 男   |   24 |
+----+------+------+------+
3 rows in set (0.00 sec)

增量備份的shell腳本

#!/bin/bash# 增量備份時復制mysql-bin.00000*的目標目錄,提前手動創建這個目錄
BakDir=/home/mysql/backup/daily
# 日志文件
LogFile=/home/mysql/backup/bak.log# mysql的數據目錄
BinDir=/var/lib/mysql-bin
# mysql的index文件路徑,放在數據目錄下的
BinFile=/var/lib/mysql-bin/mysql-bin.index# 這個是用于產生新的mysql-bin.00000*文件
/usr/local/mysql/bin/mysqladmin -uroot -ptencns152 flush-logsCounter=`wc -l $BinFile | awk '{print $1}'`
NextNum=0
# 這個for循環用于比對$Counter,$NextNum這兩個值來確定文件是不是存在或最新的
for file in `cat $BinFile`
dobase=`basename $file`NextNum=`expr $NextNum + 1`if [ $NextNum -eq $Counter ]thenecho $base skip! >> $LogFileelsedest=$BakDir/$base#test -e用于檢測目標文件是否存在,存在就寫exist!到$LogFile去if(test -e $dest)thenecho $base exist! >> $LogFileelsecp $BinDir/$base $BakDirecho $base copying >> $LogFilefifi
doneecho `date +"%Y年%m月%d日 %H:%M:%S"` $Next Bakup succ! >> $LogFile

定時備份

執行命令 crontab -e,添加如下配置

# 每個星期日凌晨3:00執行完全備份腳本
0 3 * * 0 /bin/bash -x /root/bash/Mysql-FullyBak.sh >/dev/null 2>&1# 周一到周六凌晨3:00做增量備份
0 3 * * 1-6 /bin/bash -x /root/bash/Mysql-DailyBak.sh >/dev/null 2>&1

遇到的問題

  • Can't connect to local MySQL server through socket '/tmp/mysql.sock'
mysqladmin: connect to server at 'localhost' failed
error: 'Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)'
Check that mysqld is running and that the socket: '/tmp/mysql.sock' exists

去修改mysql的配置文件,添加

[mysqladmin]
# 修改為相應的sock
socket=/var/lib/mysql/mysql.sock
  • 執行mysqldump時遇到 Unknown table 'column_statistics' in information_schema (1109)
[root@centos56 bash]# /usr/local/mysql/bin/mysqldump -uroot -ptencns152 --quick --events --all-databases --flush-logs --delete-master-logs --single-transaction > /home/mysql/backup/1.sql  
mysqldump: [Warning] Using a password on the command line interface can be insecure.
mysqldump: Couldn't execute 'SELECT COLUMN_NAME,                       JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"')                FROM information_schema.COLUMN_STATISTICS                WHERE SCHEMA_NAME = 'atd' AND TABLE_NAME = 'box_info';': Unknown table 'column_statistics' in information_schema (1109)

如果使用MySQL 8.0+版本提供的命令行工具mysqldump來導出低于8.0版本的MySQL數據庫到SQL文件,會出現Unknown table 'column_statistics' in information_schema的錯誤,因為早期版本的MySQL數據庫的information_schema數據庫中沒有名為COLUMN_STATISTICS的數據表。

解決問題的方法是,使用8.0以前版本MySQL附帶的mysqldump工具,最好使用待備份的MySQL服務器版本對應版本號的mysqldump工具,mysqldump可以獨立運行,并不依賴完整的MySQL安裝包,比如在Windows中,可以直接從MySQL安裝目錄的bin目錄中將mysqldump.exe復制到其他文件夾,甚至從一臺電腦復制到另一臺電腦,然后在CMD窗口中運行。

當前使用是的MySQL 5.7.22。把5.7.20的 MYSQL_HOME/bin/mysqldump 替換掉 5.7.22的,接著就能順利執行mysqldump了,也真是奇了怪了。

轉載于:https://www.cnblogs.com/lhat/p/10106517.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450402.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450402.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450402.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java 接口可以多繼承

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 接口是常量值和方法定義的集合。接口是一種特殊的抽象類。 java類是單繼承的。classB Extends classA java接口可以多繼承。Interface…

C語言struct關鍵字詳解—結構體

struct 是個神奇的關鍵字,它將一些相關聯的數據打包成一個整體,方便使用。在網絡協議、通信控制、嵌入式系統、驅動開發等地方,我們經常要傳送的不是簡單的字節流(char 型數組),而是多種數據組合起來的一個…

JDK1.8使用Dubbo時需注意

2019獨角獸企業重金招聘Python工程師標準>>> Dubbo自帶的很多包都比較舊了,其中的javassist在JDK1.8上運行會報錯 而且錯誤通常比較詭異,javassist是編輯和創建Java字節碼的類庫,常見的錯誤會從spring中報出 解決辦法:…

Java 11 已發布,String 還能這樣玩!

在文章《Java 11 正式發布,這 8 個逆天新特性教你寫出更牛逼的代碼》中,我有介紹到 Java 11 的八個新特性,其中關于 String 加強部分,我覺得有點意思,這里單獨再拉出來講。 Java 11 增加了一系列的字符串處理方法&…

Redis1 晨考題

Redis1 晨考題 1.Redis 是什么 ? redis 是一個開源的使用 ANSI C 語言編寫、支持網絡、可基于內存亦可持久化的日志型、Key-Value 的內存數據庫,并提供多種語言的 API。 2.NOSQL 是什么 ?出現的目的和意義是什么 ? NoSQL 泛指…

C語言void關鍵字

void 有什么好講的呢?如果你認為沒有,那就沒有;但如果你認為有,那就真的有。有點像“色即是空,空即是色”。一、void a? void 的字面意思是“空類型”,void *則為“空類型指針”,vo…

深入了解RabbitMQ工作原理及簡單使用

深入了解RabbitMQ工作原理及簡單使用 RabbitMQ系列文章 RabbitMQ在Ubuntu上的環境搭建深入了解RabbitMQ工作原理及簡單使用RabbitMQ交換器Exchange介紹與實踐RabbitMQ事務和Confirm發送方消息確認——深入解讀使用Docker部署RabbitMQ集群你不知道的RabbitMQ集群架構全解RabbitM…

使用el-checkbox實現全選,點擊失效沒有反應

最近在公司接收到了一個需求,給收藏夾的書籍添加批量、全選刪除實現思路:點擊全選改變item的checked,改變item的checked,重新便利一下所有item的checked來改變全選的selectAll1)該組件基本功能已經實現,che…

Spring3.2新注解@ControllerAdvice

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 ControllerAdvice,是spring3.2提供的新注解,從名字上可以看出大體意思是控制器增強。讓我們先看看ControllerAdv…

Mysql1 晨考題

Mysql1 晨考題 1.描述主鍵、外鍵、候選主鍵、超鍵分別是什么 ? (1)主鍵:數據庫表中對存儲數據對象給予唯一完整標識的數據列或屬性的組合。一個數據列只能有一個主 鍵,且主鍵的取值不能缺失,即不能為空值…

C語言關鍵字

C語言do、while、for關鍵字—循環 C 語言中循環語句有三種:while 循環、do-while 循環、for 循環。while 循環:先判斷while 后面括號里的值,如果為真則執行其后面的代碼;否則不執行。while(1)表示死循環。…

C語言字符篇(五)內存函數

memcpy不可以把目的地址寫成本身但是memmove可以,因為它是先保存到臨時空間 #include <string.h> void *memcpy(void *dest, const void *src, size_t n);將內存src拷貝n個字符到內存destvoid *memmove(void *dest, const void *src, size_t n);將內存src的前n個數據拷貝…

GMQ交易平臺大力探索區塊鏈技術,進一步推動產業繁榮

近年來&#xff0c;區塊鏈技術作為金融科技的中堅力量&#xff0c;受到了產業界的熱切關注&#xff0c;其實驗開展和應用研發正在如火如荼的進行。 在此背景下&#xff0c;各地涌現出一大批優秀的企業投入到區塊鏈產業中&#xff0c;各類企業投融 資活動十分活躍&#xff0c;充…

java 筆試題

JAVA-2003筆試題 一、選擇題&#xff08;每小題2&#xff0c;共10分&#xff09; 下列語句序列執行后&#xff0c;m 的值是&#xff08; C &#xff09; int a10, b3, m5; if( ab ) ma; else ma*m; A.15 B.50 C.55 D.5若已定義byte[]x{11,22,33,-66}其中0≤k≤3&#xff0c;則…

objectdatasouce的溫故

在做ecxel的時候&#xff0c;需要前臺做一個聯動的效果。 記錄一下這個數據源的用法&#xff0c;大學時候用的&#xff0c;忘得差不多了 首先就是往頁面拖拽一個objectdatasouce的控件 然后配置數據源&#xff1a; 選擇業務對象(其實就是選擇你要用的哪個類&#xff0c;如果下拉…

都會五星回評,歡迎留下地址-博客之星

歡迎五星回評地址https://bbs.csdn.net/topics/603961857

jQuery核心

jQuery(selector) jQuery 的核心功能都是通過這個函數實現的。 jQuery中的一切都基于這個函數&#xff0c;或者說都是在以某種方式使用這個函數。這個函數最基本的用法就是向它傳遞一個表達式&#xff08;通常由 CSS 選擇器組成&#xff09;&#xff0c;然后根據這個表達式來查…

Feign api調用方式

Feign使用簡介 基本用法 基本的使用如下所示&#xff0c;一個對于canonical Retrofit sample的適配。 interface GitHub {// RequestLine注解聲明請求方法和請求地址,可以允許有查詢參數RequestLine("GET /repos/{owner}/{repo}/contributors")List<Contributor&g…

預處理

C語言##預算符 和#運算符一樣&#xff0c;##運算符可以用于宏函數的替換部分。這個運算符把兩個語言符號組合成單個語言符號。看例子&#xff1a;#define XNAME(n) x ## n如果這樣使用宏&#xff1a;XNAME(8)則會被展開成這樣&#xff1a;x8看明白了沒&#xff1f; ##就是個粘合…

Lambda表達式使用2

1.概述    本篇主要介紹lambda中常用的收集器&#xff0c;收集器的作用就是從數據流中生成需要的數據接口。    最常用的就是Collectors.toList()&#xff0c;只要將它傳遞給collect()函數&#xff0c;就能夠使用它了。    在我們使用收集器的時候經常會用到“方法…