邏輯備份,mysqldump,SELECT…INTO OUTFILE,恢復


邏輯備份

mysqldump

mysqldump備份工具最初由Igor Romanenko編寫完成,通常用來完成轉存(dump)數據庫的備份以及不同數據庫之間的移植,例如從低版本的MySQL數據庫升級到高版本的MySQL數據庫,或者從MySQL數據庫移植到Oracle和SQL Server等數據庫等。

mysqldump的語法如下:

mysqldump [arguments] > file_name

如果想要備份所有的數據庫,可以使用--all-databaes選項:

mysqldump --all -databases > dump.sql

如果想要備份指定的數據庫,可以使用--databases選項:

mysqldump --databases db1 db2 db3 > dump.sql

如果想要對test這個架構進行備份,可以使用如下語句:

mysqldump --single -transaction test > test_backup.sql

我們使用--single-transaction選項來保證備份的一致性,備份出的test_backup.sql是文本文件,通過命令cat就可以查看文件的內容:cat test_backup.sql

可以看到,備份出的文件內容就是表結構和數據,所有這些都是用SQL語句表示的。文件開始和結束處的注釋是用來設置MySQL數據庫的各項參數的,一般用來使還原工作能更有效和准確的進行。之后的部分先是CREATE TABLE語句,之后就是INSERT語句了。

mysqldump的參數選項很多,可以通過mysqldump -help命令來查看所有的參數,有些參數有縮寫,如--lock-tables的縮寫為-l,重點介紹一些比較重要的參數。

--single-transaction:在備份開始前,先執行START TRANSACTION命令,以此來獲得備份的一致性,當前該參數只對InnoDB存儲引擎有效。當啟用該參數並進行備份時,確保沒有其他任何的DDL語句執行,因為一致性讀並不能隔離DDL語句。

--lock-tables(-l):在備份中,依次鎖住每個架構下的所有表。一般用於MyISAM存儲引擎,備份時只能對數據庫進行讀取操作,不過備份依然可以保證一致性。對於InnoDB存儲引擎,不需要使用該參數,用--single-transaction即可,並且-lock-tables和-single-transaction是互斥(exclusive)的,不能同時使用。如果你的MySQL數據庫中既有MyISAM存儲引擎的表,又有InnoDB存儲引擎的表,那么這時你的選擇只有--lock-tables了。另外,前面說了,--lock-tables選項是依次對每個架構中的表上鎖的,因此只能保證每個架構下表備份的一致性,而不能保證所有架構下表的一致性。

--lock-all-tables(-x):在備份過程中,對所有架構中的所有表上鎖。這可以避免之前提及的--lock-tables參數不能同時鎖住所有表的問題。

--add-drop-database:在CREATE DATABASE前先運行DROP DATABASE。這個參數需要和-all-databases或者-databases選項一起使用。默認情況下,導出的文本文件中並不會有CREATE DATABASE,除非你指定了這個參數,因此可能會看到如下內容:

mysqldump --single -transaction --add -drop -database --databases test > test_backup.sql

cat test_backup.sql

--master-data[=value]:通過該參數產生的備份轉存文件主要用來建立一個slave replication。當value的值為1時,轉存文件中記錄CHANGE MASTER語句;當value的值為2時,CHANGE MASTER語句被寫成SQL注釋。默認情況下,value的值為空。

當value值為1時,在備份文件中會看到:

mysqldump --single -transaction --add -drop -database --master -data=1 --databases test>test_backup.sql

cat test_backup.sql

CHANGE MASTER TO MASTER_LOG_FILE='xen-server-bin.000006',MASTER_LOG_POS=8095;

當value為2時,在備份文件中會看到CHANGE MASTER語句被注釋了:

mysqldump --single -transaction --add -drop -database --master -data=1 --databases test>test_backup.sql

cat test_backup.sql

--Position to start replication or point-in-time recovery from

--master-data會自動忽略-lock-tables選項。如果沒有使用-single-transaction選項,則會自動使用-lock-all-tables選項。

--events(-E):備份事件調度器。

--routines(-R):備份存儲過程和函數。

--triggers:備份觸發器。

--hex-blob:將BINARY、VARBINARY、BLOG、BIT列類型備份為十六進制的格式。mysqldump導出的文件一般是文本文件,但是,如果導出的數據中有上述這些類型,文本文件模式下可能有些字符不可見,若添加-he-blob選項,結果會以十六進制的方式顯示,如:

mysqldump --single -transaction --add -drop -database --master -data=2 --no -autocommit --databases test3 > test3_backup.sql

cat test3_backup.sql

LOCK TABLES'a'WRITE;

set autocommit=0;

INSERT INTO'a'VALUES(0x61000000000000000000);

UNLOCK TABLES;

可以看到,這里用0x61000000000000000000(十六進制的格式)來導出數據。

--tab=path(-T path):產生TAB分割的數據文件。對於每張表,mysqldump創建一個包含CREATE TABLE語句的table_name.sql文件和包含數據的tbl_name.txt。可以使用--fields-terminated-by=……,--fields-enclosed-by=……,--fields-optionally-enclosed-by=……,--fields-escaped-by=……,--lines-terminated-by=……來改變默認的分割符、換行符等,如:

mysqldump --single -transaction --add -drop -database --tab="/usr/local/mysql/data/test" test

大多數DBA喜歡用SELECT……INTO OUTFILE的方式來導出一張表,但是通過mysqldump一樣可以完成工作,而且可以一次完成多張表的導出,並且保證導出數據的一致性。

--where='where_condition'(-w 'where_condition'):導出給定條件的數據。

例如,導出b架構下的表a,並且表a的數據大於2,如下所示。

mysqldump --single -transaction --where='b>2' test a > a.sql

SELECT……INTO OUTFILE

SELECT……INTO語句也是一種邏輯備份的方法,或者更准確地說是導出一張表中的數據。

SELECT……INTO的語法如下:

SELECT [column 1], [column 2]……

INTO

OUTFILE 'file_name'

[{FIELDS|COLUMNS}

  [TERMINATED BY'string']

  [[OPTIONALLY]ENCLOSED BY'char']

  [ESCAPED BY'char']

]

[LINES

  [STARTING BY'string']

  [TERMINATED BY'string']

]

FROM TABLE WHERE……

字段[TERMINATED BY 'string']表示每個列的分隔符,

[[OPTIONALLY]ENCLOSED BY'char']表示對於字符串的包含符,

[ESCAPED BY'char']表示轉義符,

[STARTING BY'string']表示每行的開始符號,

TERMINATED BY'string'表示每行的結束符號。

如果沒有指定任何FIELDS和LINES的選項,默認使用以下的設置:

FIELDS TERMINATED BY '\t'

ENCLOSED BY ''

ESCAPED BY '\\'

LINES TERMINATED BY '\n'

STARTING BY ''

file_name表示導出的文件,但文件所在的路徑的權限必須是mysql:mysql,否則MySQL會報告沒有權限導出:

select * into outfile '/root/a.txt' from a;

ERROR 1(HY000):Can't create/write to file'/root/a.txt'(Errcode:13)

查看通過SELECT INTO導出的表a文件:

select * into outfile '/home/mysql/a.txt' from a;

quit

cat /home/mysql/a.txt

1 a

2 b

可以發現,默認導出的文件是以TAB進行列分割的,如果想要使用其他分割符,如“,”,則可以使用FIELDS TERMINATED BY'string'選項,如:

mysql test -e "select * into outfile '/home/mysql/a.txt' fields terminated by','from a";

cat /home/mysql/a.txt

1,a

2,b

在Windows平台下,因為其換行符是“\r\n”,因此在導出時可能需要指定LINES TERMINATED BY選項,如:

mysql test -e "select * into outfile '/home/mysql/a.txt' fields terminated by',' lines terminated by '\r\n' from a";

od -c a.txt

0000000 1,a\r\n 2,b\r\n 3

0000017

邏輯備份的恢復

mysqldump的恢復

mysqldump的恢復操作比較簡單,因為備份的文件就是導出的SQL語句,一般只需要執行這個文件就可以了,可以通過以下的方法:

mysql -uroot -p123456<test_backup.sql

如果在導出時包含了創建和刪除數據庫的SQL語句,則必須確保刪除架構時架構目錄下沒有其他與數據庫無關的文件,否則可能會出現以下的錯誤:

drop database test;

ERROR 1010(HY000):Error dropping database(can't rmdir'./test',errno:39)

因為邏輯備份的文件是由SQL語句組成的,所以也可以通過SOURCE命令來執行導出的邏輯備份文件,如下所示:

source /home/mysql/test_backup.sql;

Query OK,0 rows affected(0.00 sec)

……

Query OK,0 rows affected(0.00 sec)

通過mysqldump可以恢復數據庫,但是常發生的一個問題是mysqldump可以導出存儲過程、觸發器、事件、數據,但是卻不能導出視圖。因此,如果你的數據庫中還使用了視圖,那么在用mysqldump備份完數據庫后還需要導出視圖的定義,或者保存視圖定義的frm文件,並在恢復時進行導入,這樣才能保證mysqldump數據庫的完全恢復。

LOAD DATA INFILE

若是通過mysqldump --tab或SELECT INTO OUTFILE導出的數據需要恢復時,這時需要通過LOAD DATA INFILE命令來進行導入。

LOAD DATA INFILE的語法如下所示:

LOAD DATA [LOW_PRIORITY|CONCURRENT] [LOCAL] INFILE 'file_name'

[REPLACE|IGNORE]

INTO TABLE tbl_name

[CHARACTER SET charset_name] 

[{FIELDS|COLUMNS}

  [TERMINATED BY'string']

  [[OPTIONALLY]ENCLOSED BY'char']

  [ESCAPED BY'char']

]

[LINES

  [STARTING BY'string']

  [TERMINATED BY'string']

]

[IGNORE number LINES]

[(col_name_or_user_var,……)]

[SET col_name=expr,……]

要對服務器文件使用LOAD DATA INFILE,必須擁有FILE權,其中導入格式的選項和之前介紹的SELECT INTO OUTFILE命令完全一樣。IGNORE number LINES選項可以忽略導入的前幾行。

下面來看一個用LOAD DATA INFILE命令導入文件的示例,並忽略第一行的導入:

load data infile '/home/mysql/a.txt' into table a;

為了加快InnoDB存儲引擎的導入,你可能希望導入過程忽略對外鍵的檢查,因此可以使用如下方式。

set @@foreign_key_checks=0;

load data infile '/home/mysql/a.txt' into table a;

set @@foreign_key_checks=1;

可以針對指定的列進行導入,如將數據導入列a、b,而c列等於a、b列之和:

create table b(a int,b int,c int,primary key(a))engine=innodb;

load data infile '/home/mysql/a.txt' into table b fields terminated by ',' (a,b) set c=a+b;

LOAD DATA INFILE命令可以用來導入數據,但同時可以完成對Linux操作系統的監控。如果需要監控CPU的使用情況,可以通過加載/proc/stat來完成。

首先我們需要建立一張監控CPU的表cpu_stat,其結構如下所示:

CREATE TABLE IF NOT EXISTS DBA.cpu_stat(

  id bigint auto_increment primary key,

  value char(25) NOT NULL,

  user bigint,

  nice bigint,

  system bigint,

  idle bigint,

  iowait bigint,

  irq bigint,

  softirq bigint,

  steal bigint,

  guest bigint,

  other bigint,

  time datetime

);

接着可以通過用LOAD DATA INFILE命令來加載/proc/stat文件,但需要對其中一些數值進行轉化,命令如下所示:

LOAD DATA INFILE '/proc/stat'
IGNORE INTO TABLE DBA.cpu_stat
FIELDS TERMINATED BY''
(@value,@val1,@val2,@val3,@val4,@val5,@val6,@val7,@val8,@val9,@val10)
SET
value=@value,
user=IF(@value NOT LIKE 'cpu%', NULL,IF(@value!='cpu',IFNULL(@val1,0),IFNULL(@val2,0))),
nice=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val2,0),IFNULL(@val3,0))),
system=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val3,0),IFNULL(@val4,0))),
idle=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val4,0),IFNULL(@val5,0))),
iowait=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val5,0),IFNULL(@val6,0))),
irq=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val6,0),IFNULL(@val7,0))),
softirq=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val7,0),IFNULL(@val8,0))),
steal=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val8,0),IFNULL(@val9,0))),
guest=IF(@value NOT LIKE 'cpu%',NULL,IF(@value!='cpu',IFNULL(@val9,0),IFNULL(@val10,0))),
other=IF(@value like 'cpu%',user+nice+system+idle+iowait+irq+softirq+steal+guest,@val1),
time=now();

接着查看表cpu_stat,可以看到類似如下的內容:

select * from cpu_stat\G

***************************1.row***************************

id:1

value:cpu

user:2632896

nice:67761

system:688488

idle:4136329105

iowait:1468238

irq:0

softirq:106303

steal:148300

guest:0

other:4141441091

time:2010-09-10 12:01:04

 

***************************14.row***************************

id:14

value:procs_running

user:NULL

nice:NULL

system:NULL

idle:NULL

iowait:NULL

irq:NULL

softirq:NULL

steal:NULL

guest:NULL

other:1

time:2010-09-10 12:01:04

***************************15.row***************************

id:15

value:procs_blocked

user:NULL

nice:NULL

system:NULL

idle:NULL

iowait:NULL

irq:NULL

softirq:NULL

steal:NULL

guest:NULL

other:0

time:2010-09-10 12:01:04

15 rows in set(0.00 sec)

接着可以設置一個定時器來讓MySQL數據庫自動地運行上述LOAD DATA INFILE語句,這樣就會有每個時間點的CPU信息被記錄到表cpu_stat。

執行下述語句就可以得到每個時間點上CPU的使用情況:

select
  100*((new.user-old.user)/(new.other-old.other))user,
  100*((new.nice-old.nice)/(new.other-old.other))nice,
  100*((new.system-old.system)/(new.other-old.other))system,
  100*((new.idle-old.idle)/(new.other-old.other))idle,
  100*((new.iowait-old.iowait)/(new.other-old.other))iowait,
  100*((new.irq-old.irq)/(new.other-old.other))irq,
  100*((new.softirq-old.softirq)/(new.other-old.other))softer,
  100*((new.steal-old.steal)/(new.other-old.other))steal,
  100*((new.guest-old.guest)/(new.other-old.other))guest,
  new.time
from DBA.cpu_stat old,
  DBA.cpu_stat new
where new.id-15=old.id
  and old.value='cpu'
  and new.value=old.value\G;

同樣,我們還可以對/proc/diskstat文件執行如上述所示的操作,這樣就又可以對磁盤進行監控操作了。

mysqlimport

mysqlimport是MySQL數據庫提供的一個命令行程序,從本質上來說,是LOAD DATA INFILE的命令接口,而且大多數的選項都和LOAD DATA INFILE語法相同。其語法格式如下:

mysqlimport [options] db_name textfile1[textfile2……]

與LOAD DATA INFILE不同的是,mysqlimport命令是可以導入多張表的,並且通過--user-thread參數來並發導入不同的文件。這里的並發是指並發導入多個文件,並不是指mysqlimport可以並發地導入一個文件,這是有區別的,並且並發地對同一張表進行導入,效果一般都不會比串行的方式好。

通過mysqlimport並發地導入兩張表。

mysqlimport --use -threads=2 test /home/mysql/t.txt /home/mysql/s.txt

如果在上述命令運行的過程中查看MySQL的數據庫線程列表,應該可以看到類似如下的內容:

show full processlist\G

***************************1.row***************************

Id:46

User:rep

Host:www.dao.com:1028

db:NULL

Command:Binlog Dump

Time:37651

State:Master has sent all binlog to slave;waiting for binlog to be updated

Info:NULL

***************************2.row***************************

Id:77

User:root

Host:localhost

db:test

Command:Query

Time:0

State:NULL

Info:show full processlist

***************************3.row***************************

Id:83

User:root

Host:localhost

db:test

Command:Query

Time:73

State:NULL

Info:LOAD DATA INFILE '/home/mysql/t.txt' INTO TABLE 't' IGNORE 0 LINES

***************************4.row***************************

Id:84

User:root

Host:localhost

db:test

Command:Query

Time:73

State:NULL

Info:LOAD DATA INFILE '/home/mysql/s.txt' INTO TABLE 's' IGNORE 0 LINES

4 rows in set(0.00 sec)

mysqlimport實際上是同時執行了2條LOAD DTA INFILE語句來完成並發導入操作。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM