需求场景:
作为一个站长,能掌握备份还原自己小站的数据是至关重要的,不然一生的心血岂不是不复存在,万劫不复的心都有了。今天博主就wordpress博客站点总结一下手动备份还原数据的过程以及升级小站的要点。为什么要手动,有道友会说不是有很多插件吗,博主认为只有手动备份才能更清晰的了解自己小站的数据结构,才能够更快速的定位和解决疑难杂症。
一、手动备份
备份分为几个部分,数据库、主题配置、主题目录、多媒体目录、站点配置文件、全站目录备份;
①、首先是数据库,这个至关重要。
数据中包含博客站点的配置信息、用户信息、文章、评论、分类、标签、等等各种关联信息;
虽然说了是手动备份,但要是拿不准,也可以使用一些插件如WP-DB-Backup并可以配置定时自动备份;
另外你也可以使用php的phpmyadmin来备份数据库,但是今天我们要说的是使用mysql命令来手动备份数据库。
lamp环境:linux + Apache+php + mysql ;创建一个库“wp-data”给用户“wp”使用,密码是“123456”;
现在我们开始备份wp-data这个数据库吧:
[root@Moni ~]# su - mysql
[mysql@Moni ~]$ mysqldump -h localhost -u wp -p wp-data >./wp-sql-bak-2017-9-16.sql
Enter password: 123456
[mysql@Moni ~]$ ll -h
-rw-rw-r--. 1 mysql mysql 3.1M 9月 18 11:30 wp-sql-bak-2017-9-16.sql
命令mysqldump导出数据库,“-u”指定使用用户、“-p”使用密码、“wp-data”为库名、“>”导出符号到某个目录下的某个文件。
如果要导出整个数据库所有库的数据,则使用"--all-databases"参数。
当然我们也可以用“-d”参数道出库表结构或某个表的表结构;
<导出wp-data库中的wp_users表的数据>
[mysql@Moni ~]$ mysqldump -h localhost -u wp -p wp-data wp_users >./wp-sql-bak-2017-9-16.sql
<导出wp-data库的表结构>
[mysql@Moni ~]$ mysqldump -h localhost -u wp -p -d wp-data >./wp-sql-bak-2017-9-16.sql
<导出wp-data库中wp_users表的表结构>
[mysql@Moni ~]$ mysqldump -h localhost -u wp -p -d wp-data wp_users >./wp-sql-bak-2017-9-16.sql
②、主题配置、站点配置、多媒体。
有些主题模板,后台支持配置模块,比如开启音乐列表,主题背景,等等,这些配置一般都有备份导出的地方,就不多说了。
关于站点的配置文件,如站点根目录下的wp-config.php文件,这里也直接拷贝即可。
最后当然是多媒体的的备份了,一般在站点根目录下的:"./wp-content/uploads/";
③、主题目录或全站目录备份;
及时备份主题目录,才能避免自己心仪的主题和站点长长久久;
注意,当我们备份完数据库时,最好是把站点的http服务关闭,避免动态网站更新改动数据。
我们只需要进入到站点下的“./wp-content/themes/”目录下,找到自己主题的目录,直接拷贝备份或是压缩备份即可:
[wp@Moni themes]$ tar -zcvf /home/wp/themes-2017-9-18-backup.tar.gz ./jinsomB
建站过程中,只要我们不对wordpress目录的文件做过修改,备份了数据库、主题目录、主题和站点配置文件、多媒体、已经可以进行迁移或恢复工作了。
但事实上,不可避免的我们会做过一些改动的优化,往往我们还记不得改了哪里。所以有时候为了我们的数据能够正常运行,可以对整个站点目录进行备份,方法是一样的。
[wp@Moni htdocs]$ tar -zcvf /home/wp/wp-all-bakcup-2017-9-18.tar.gz ./*
最后有必要的情况下,我们还可以对整个站点环境进行备份,即lamp环境:
[root@Moni ~]# tar -zcPvf /home/wp/lamp-wp-backup-2017-9-19.tar.gz -h --dereference /home/wp/.[!.]* /home/mysql/.[!.]* /usr/local/apache /usr/local/php /usr/local/mysql /usr/local/apr /usr/local/apr-util /usr/local/pcre /etc/init.d/mysql /etc/init.d/httpd
可以看到我对php、apache、mysql、apr、apr-util、pcre、mysql和httpd服务程序文件、wp和mysql两个用户宿主目录下的隐藏文件。
其中tar的“-P”参数是不从文件名中取出“ /”符号、“-h --dereference”参数表示为归档符号连接文件指向的真实源目录和子文件。
此外我们要想定期备份我们的站点主题目录,也可以使用增量备份的方法减少备份使用的空间和时间。
<-查看归档文件中的文件列表->
[root@Moni ~]# tar -ztPGvvf themes-2017-9-18-backup.tar.gz
-rw------- wp/wp 16531 2017-09-19 11:56
、、、、、、(Gvv显示属性)
<-主题目录文件若更新后增量备份->
[root@Moni ~]#tar -czpvf themes-backup001.tar.gz -g ./themes.snap /usr/、、、/themes/my/*
<-当我修改了my主题目录中functions.php文件后,进行第二次增量备份->
[root@Moni ~]#tar -czpvf themes-backup002.tar.gz -g ./themes.snap /usr/、、、/themes/my/*
其中“-g ./themes.snap”是指定增量信息文件,增量归档时需要依靠这个文件做比较。那么backup001和002有什么区别呢?
区别就是001的归档文件,是最开始的一份完整的整个目录的文件,002归档的文件则只有修改了的functions.php文件。
当然恢复的时候也就需要先恢复001在恢复002了,那么tar是如何判断更新的文件并进行归档的呢?
事实上,linux中的文件,有三个时间属性:mtime、atime、ctime
分别表示:文件修改时间、文件访问时间、文件属性的修改时间。
ctime文件属性修改时间即属性和权限发生改变时更新的时间可以使用命令“ls -lc”查看;
mtime文件修改后更新的时间可以通过“ls -l”查看、atime访问即更新可以通过“ls -lu”查看;
其中tar在归档文件是,非常依赖的是atime这个时间属性,也就是说只要有访问,002中都会对其重新归档。当然包括修改的和新创建的文件了。
二、手动还原
还原恢复数据,比之备份数据时更要小心谨慎,恢复之前也要对当前数据进行备份,除非你能完全掌控。
如果会恢复站点目录或主题目录,则关闭正在运行的httpd和mysql服务,备份后覆盖式恢复,或是把当前目录下文件mv移动到其它目录,再进行解压恢复。
[root@Moni ~]# tar zxpvf /themes.tar.gz -C /
可以“-C”参数指定解压目录,但如果压缩备份时加了“-P”参数,则也可以直接指定向根目录。
当然也可以“-P”直接恢复到原先备份时的目录,前提是备份时也加了“-P”参数。
[root@Moni ~]# tar zxPpGvvf /themes.tar.gz
这里主要介绍下恢复数据库:
数据库的恢复同样要考虑到当前数据的备份,大致分为两种,一种所有数据恢复到备份时状态、一种是只恢复部分数据,如误删除的数据条目,或是从其它站点迁移过来的数据;
前者我们可以直接把当前库备份删除,然后还原到以前的状态即可。后者则更像向表中添加或替换数据。
我们先看一下整个库的恢复:
我们可以直接删除库,也可以删除库中所有相关数据,建议后者,因为删除库后新建库,还要配置库的相关用户权限。
<-删除整个库,需要先查看一下用户和库的权限->
[mysql@Moni ~]$ mysql -u wp -p
Enter password: 123456
Welcome to the MySQL monitor. Commands end with ; or \g.
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| test |
| wp-data |
+--------------------+
3 rows in set (0.00 sec)
mysql> select db,user,host from mysql.db;
+---------+------+------+
| db | user | host |
+---------+------+------+
| test | | % |
| wp-data | wp |localhost |
+---------+------+------+
2 rows in set (0.00 sec)
<--可以看到这里wp-data库和用户wp有关联并且在localhost的权限-->
mysql> show grants for 'wp'@'localhost';
+-------------------------------------------------------------------------------------------------------+
| Grants for wp@localhost |
+-------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'wp'@'localhost' IDENTIFIED BY PASSWORD '*B5584DB495*****817294***D76A43*****' |
| GRANT USAGE ON `wp-data`.* TO 'wp'@'localhost' WITH GRANT OPTION |
+-------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
<--可见wp用户在localhost的grant权限只有wp-data库,即库允许wp用户在本地访问。-->
<-我们也可以查看所有mysql用户或单个用户的权限->
mysql> SELECT DISTINCT CONCAT('User: ''',user,'''@''',host,''';') AS query FROM mysql.user;
mysql> select * from mysql.user where user='oxblog'\G
<--除此之外我们还要查看当前数据库的字符集和排列规则->
mysql> use wp-data
Database changed
mysql> show variables like 'character_set_database';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| character_set_database | utf8 |
+------------------------+-------+
1 row in set (0.00 sec)
mysql> show variables like 'collation_database';
+--------------------+-----------------+
| Variable_name | Value |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
1 row in set (0.00 sec)
<-然后我们便可以删除数据库、创建数据库、并重新赋予用户权限->
mysql> drop database wp_data;
Query OK, 0 rows affected (0.00 sec)
mysql> create database if not exists wp_data character set 'utf8' collate 'utf8_general_ci';
Query OK, 1 row affected (0.00 sec)
<--这里“if not exists”表示即使wp_data库没有删除,也会覆盖式的重新创建;-->
grant all privileges on wp-data.* to wp@'localhost' identified by 'password****' with grant option;
Query OK, 0 rows affected (0.00 sec)
mysql> use wp-data;
Database changed
mysql> source /home/mysql/wp-sql-bak-2017-9-16.sql;
好了,到此我们的数据就已经恢复,并还原了之前的用户权限和密码;
简单点方法的就是删除里面所有表,并不删除库,然后直接还原即可:
mysql> use heping;
Database changed
mysql> select concat('drop table ',table_name,';') from information_schema.`tables` where table_schema='heping';
+--------------------------------------+
| concat('drop table ',table_name,';') |
+--------------------------------------+
| drop table mytable; |
| drop table mytable001; |
| drop table mytable002; |
| drop table mytable003; |
+--------------------------------------+
4 rows in set (0.00 sec)
这样直接复制上面列表批量删除即可,然后恢复即可;
mysql>source /home/mysql/heping-sql-bak-2017-9-16.sql;
(注意:这里恢复数据是,备份的sql文件对应的数据库名和用户和恢复时的应该一致,否则会报错)
但如果我们直接执行source恢复,相当于把所有的sql执行了一遍,很有可能会对现有数据造成损坏。
有时候我们只需要简单的恢复其中某条数据或是某个表,我的建议是,新建一个数据库,把备份的数据导入进去,然后对比进行恢复。
mysql> select * from mytable where id='1';
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
如上面这条数据,我们把它直接导出来:
mysql> desc heping.mytable;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(1) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
| date | date | YES | | NULL | |
| data | char(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
4 rows in set (0.01 sec)
mysql> create database if not exists fuqiang character set 'utf8' collate 'utf8_general_ci';
Query OK, 1 row affected (0.00 sec)
mysql> create table fuqiang.mytable (id varchar(1),name varchar(20),date date,data char(20));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into fuqiang.mytable (id,name,date,data) select * from heping.mytable where id='1';
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from heping.mytable where id=1;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
mysql> select * from fuqiang.mytable;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.01 sec)
可以看到,我新建一个数据库,然后在新库中新建一个表结构一样的表,使用insert into 、select from 语法直接从备库中导入数据;
但是这仅适用于新库中没有这条数据或这条数据已被删除时使用。
重要的是如果已经有此条目或执行多次,则会导入多条内容。
mysql> select * from fuqiang.mytable;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
3 rows in set (0.00 sec)
当然我们也可以使用mysqldump命令或是select语句导出再导入;
dump是在linux的shell下执行,select是在sql控制终端下执行,且前者导出的是sql语句格式,后者导出的则是数据格式文件。
mysql> select * from heping.mytable where id=1 into outfile '/home/mysql/back001.txt';
Query OK, 1 row affected (0.01 sec)
[root@Moni mysql]# cat back001.txt
1 001 2017-09-19 welcom i'm first dat
当然我们也可以使用参数来设置输出数据的格式结构:
cmysql> select * from heping.mytable where id=1 into outfile '/home/mysql/back002.txt' fields terminated by ',' optionally enclosed by '"' lines terminated by '\n';
Query OK, 1 row affected (0.00 sec)
[root@Moni mysql]# cat back002.txt
"1","001","2017-09-19","welcom i'm first dat"
可以看到输出文本结果数据结构每个字段用双引号包含,每个字段中间用逗号隔开,并每条数据各起一行;
当然这种select导出的数据文件输出文件需要是新文件,对输出目录需要有读写权限;
select导出是直接数据格式,导入时则需要在sql控制终端使用load data、into table命令导入数据;
cmysql> load data local infile '/home/mysql/back001.txt' into table heping.mytable002;
Query OK, 1 row affected (0.00 sec)
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
mysql> select * from heping.mytable002;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
注意load data 命令导入时,需要按照数据表结构列的顺序插入数据,如果不一致则需要指定列的顺序;
如果输入文件是back002.txt被指定了数据结构,导入时也需要指定,否则数据不能完整导入,back001.txt默认格式导出,则导入时直接导入即可;
mysql> load data local infile '/home/mysql/back002.txt' into table heping.mytable003 fields terminated by ',' optionally enclosed by '"' lines terminated by '\n' (id,name,date,data);
Query OK, 2 rows affected, 1 warning (0.01 sec)
Records: 2 Deleted: 0 Skipped: 0 Warnings: 1
mysql> select * from heping.mytable003;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 2 | 002 | 2017-09-20 | welcom i'm second da |
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
2 rows in set (0.00 sec)
看到上面我添加了second数据,但是导入并不完整,这是因为data字段限制了char字节数;
而mysqldump命令导出单条或多条数据,和上面导出整个库和表基本是一样的,但使用“--where”参数来筛选条件;
[root@Moni mysql]# mysqldump -u wp -p 123456 heping mytable001 --where=" id=1 " > /home/mysql/back001.sql
[root@Moni mysql]# cat back001.sql
、、、、、、
-- Host: localhost Database: heping
-- Dumping data for table `mytable001`
、、、、、、
-- WHERE: id=1
LOCK TABLES `mytable001` WRITE;
/*!40000 ALTER TABLE `mytable001` DISABLE KEYS */;
INSERT INTO `mytable001` VALUES ('1','001','2017-09-19','welcom i\'m first dat');
/*!40000 ALTER TABLE `mytable001` ENABLE KEYS */;
UNLOCK TABLES;
、、、、、、
-- Dump completed on 2017-09-29 12:47:36
如果是多个条件则可用“and”或“or”来进行组合使用,如上导出的sql格式文件,内容比较臃肿;
而mysqldump导出的sql文件,导入时针对不同的情况斟酌处理;
首先是导出导入所有库的sql文件:
[root@Moni mysql]# mysqldump -u root --all-databases > /home/mysql/alldataback.sql
[root@Moni mysql]# mysql -u root
mysql> source alldataback.sql
Query OK, 53 rows affected (0.00 sec)
其次是导出导入某些库或是单个库:
[root@Moni mysql]# mysqldump -u root --databases heping fuqiang >/home/mysql/hpfq.sql
[root@Moni mysql]# mysql -u root
mysql> source hpfq.sql
Query OK, 40 rows affected (0.00 sec)
然后是导出导入某些表:
[root@Moni mysql]# mysqldump -u root heping mytable001 mytable002 mytable003 > /home/mysql/hepingtable.sql
[root@Moni mysql]# mysql -u root heping < /home/mysql/hepigntable.sql<或是>
[root@Moni mysql]# mysql -u root
mysql> use heping
Database changed
mysql> source /home/mysql/hepingtable.sql
Query OK, 40 rows affected (0.00 sec)
最后就是导入某个表中的某条数据,能不能实现呢?我们使用上面导出的mytable001.sql文件;
mysql> use heping;
Database changed
mysql> insert into mytable001 (id,name,date,data) values ("2","002","2017-09-29","welcom to my home");
Query OK, 1 row affected (0.00 sec)
mysql> select * from mytable001;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
| 2 | 002 | 2017-09-29 | welcom to my home |
+------+------+------------+----------------------+
2 rows in set (0.00 sec)
mysql> source /home/mysql/mytable001.sql;
Query OK, 0 rows affected (0.00 sec)
、、、、、、
mysql> select * from mytable001;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
mysql> delete from mytable001;
Query OK, 1 row affected (0.00 sec)
mysql>exit
[root@Moni mysql]# mysql -u root heping < /home/mysql/mytable001.sql
[root@Moni mysql]# mysql -u root
mysql> select * from heping.mytable001;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
可以看到这样恢复之后,是覆盖式导入,会把原先整个表清空覆盖;
那么我们能不能把其导入另外一个库中呢?答案当然是可能的,但是如此就需要我们手动查询并插入到旧库中了:
mysql> use fuqiang
Database changed
mysql> show tables;
+-------------------+
| Tables_in_fuqiang |
+-------------------+
| mytable |
+-------------------+
1 row in set (0.00 sec)
mysql> source /home/mysql/mytable001.sql;
Query OK, 0 rows affected (0.00 sec)
、、、、、、
mysql> show tables;
+-------------------+
| Tables_in_fuqiang |
+-------------------+
| mytable |
| mytable001 |
+-------------------+
2 rows in set (0.00 sec)
然后我们使用上面用到的insert into 、select命令从临时库中查询并插入到旧库;
cmysql> delete from heping.mytable001;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into heping.mytable001 (id,name,date,data) select * from fuqiang.mytable001;
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from heping.mytable001;
+------+------+------------+----------------------+
| id | name | date | data |
+------+------+------------+----------------------+
| 1 | 001 | 2017-09-19 | welcom i'm first dat |
+------+------+------------+----------------------+
1 row in set (0.00 sec)
所以,如果是整个库或表的备份,建议使用sqldump命令,如果是单条数据建议使用select导出;
注意:如果source导入数据提示超出byte时,修改mysql.ini文件,【mysqli】下修改“max_allowed_packet=100M”
三、手动升级
使用wordpres的老铁们都知道,如果你直接从后台更新站点,那么很荣幸的恭喜你,可能导致站点各种故障。
所以掌握如何手动升级我们的站点,是一件非常让人放心的事情:
①、备份程序文件和数据库,参考第一节内容。
②、下载最新的wordpress的站点程序:wordpress简体中文网 、或是wordpress后台更新页面下载。
③、解压下载的zip文件夹到某个目录如/webnews/,删除其中的wp-content目录。
(你的站点个人数据基本都在这个里面,主题、插件、多媒体等等,这个目录一般也不需要更新)
④、然后备份站点根目录下的wp配置文件wp-config.php,里面包含wp的一些初始化配置,如mysql的链接和密码;
⑤、然后把/webnews/目录下的所有文件拷贝到站点根目录下,但是我的建议是,把整个旧站点文件拷贝移动到其它目录下,然后把新包解压到站点根目录,在从旧文件目录下把wp-content目录和wp-config.php文件拷贝还原。
⑥、浏览器登录https://oxblog.cn/wp-admin/upgrade.php,更新数据库,并更新完毕。
(今天的分享就到这里,如果您有高见或好的分享,记得留言哦!)
支持一下,不虚此行!
每逢佳节倍思亲,看你博客很用心!
@沃八达 欢迎经常莅临。