大发体育娱乐在线-大发体育娱乐官方网站-大发体育娱乐登录网址
做最好的网站

mysql逻辑备份,深入理解MySQL系列

来源:http://www.dfwstonefabricators.com 作者:关于计算机 人气:67 发布时间:2019-12-11
摘要:作/译者:叶金荣(Email:[email protected]),来源: MySQL逻辑备份mysqldump是我们平时用的比较多的备份方式,那么myqldump的备份原理是什么?是如何保证备份数据一致性的呢? 为了观察my

作/译者:叶金荣(Email: [email protected]),来源:

MySQL逻辑备份mysqldump 是我们平时用的比较多的备份方式,那么myqldump的备份原理是什么?是如何保证备份数据一致性的呢?
为了观察mysql在逻辑备份mysqldump 的时候,究竟做了哪些操作,我们开启全量日志!
图片 1
然后我们开始我们的备份操作:mysqldump -uroot -p123456 --master-data=2 --single-transaction -A >/tmp/yh1.sql
这里说说比较重要的两个参数:
--single-transaction
图片 2
在开启dump操作时,会创建一个快照,这相当于此刻的一致性视图,即在整个dump的过程中是被当做一个事务的,这样就能保证同一事务下读取的数据都是一致的。但是此时如果有其他会话在做DDL操作(ALTER/DROP/RENAME/TRUNCATE TABLE),则会破坏数据的一致性,所以需要添加lock-tables锁住表用来保证数据的一致性。
--master-data
图片 3
此命令是为了获取在dump时候的master 的binlog文件名和position的位置。当他等于1时,显示change master的输出结果。等于2时,注释掉此命令的输出结果。由此我们可以知道,当等于1时dump出来的数据,恢复在slave上是非常方便的。

0、前言

本文主要探讨 mysqldump 的几种主要工作方式,并且比较一下和 mk-parralel-dump 的一些差异,为备份方式的选择提供更多的帮助。

现在我们查看刚才我们备份时候的全量日志,日质量比较打,我贴出部分主要的,
2017-12-07T07:32:24.917291Z 40 Connect root@localhost on using Socket
2017-12-07T07:32:24.917690Z 40 Query /!40100 SET @@SQL_MODE='' /
2017-12-07T07:32:24.926840Z 40 Query /!40103 SET TIME_ZONE='+00:00' /
2017-12-07T07:32:24.927033Z 40 Query FLUSH /!40101 LOCAL / TABLES
2017-12-07T07:32:24.928911Z 40 Query FLUSH TABLES WITH READ LOCK
2017-12-07T07:32:24.928994Z 40 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2017-12-07T07:32:24.929079Z 40 Query START TRANSACTION /!40100 WITH CONSISTENT SNAPSHOT /
2017-12-07T07:32:24.929252Z 40 Query SHOW VARIABLES LIKE 'gtid_mode'
2017-12-07T07:32:24.992104Z 40 Query SELECT @@GLOBAL.GTID_EXECUTED
2017-12-07T07:32:24.992528Z 40 Query SHOW MASTER STATUS
2017-12-07T07:32:24.992613Z 40 Query UNLOCK TABLES
2017-12-07T07:32:24.992735Z 40 Query SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL AND LOGFILE_GROUP_NAME IS NOT NULL GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE, TOTAL_EXTENTS, INITIAL_SIZE ORDER BY LOGFILE_GROUP_NAME
2017-12-07T07:32:24.995255Z 40 Query SELECT DISTINCT TABLESPACE_NAME, FILE_NAME, LOGFILE_GROUP_NAME, EXTENT_SIZE, INITIAL_SIZE, ENGINE FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
2017-12-07T07:32:24.996104Z 40 Query SHOW DATABASES
2017-12-07T07:32:24.997945Z 40 Query SHOW VARIABLES LIKE 'ndbinfo_version'
2017-12-07T07:32:24.999984Z 40 Init DB mysql
2017-12-07T07:32:25.000096Z 40 Query SHOW CREATE DATABASE IF NOT EXISTS mysql
2017-12-07T07:32:25.000211Z 40 Query SAVEPOINT sp
2017-12-07T07:32:25.000314Z 40 Query show tables
省略…………………………
2017-12-07T07:32:25.142111Z 40 Query use yhte
2017-12-07T07:32:25.142187Z 40 Query select @@collation_database
2017-12-07T07:32:25.142272Z 40 Query SHOW TRIGGERS LIKE 't'
2017-12-07T07:32:25.142579Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.142651Z 40 Query ROLLBACK TO SAVEPOINT sp
2017-12-07T07:32:25.142714Z 40 Query RELEASE SAVEPOINT sp
2017-12-07T07:32:25.142775Z 40 Init DB yhtest
2017-12-07T07:32:25.142830Z 40 Query SHOW CREATE DATABASE IF NOT EXISTS yhtest
2017-12-07T07:32:25.142991Z 40 Query SAVEPOINT sp
2017-12-07T07:32:25.143060Z 40 Query show tables
2017-12-07T07:32:25.143298Z 40 Query show table status like 't1'
2017-12-07T07:32:25.143799Z 40 Query SET SQL_QUOTE_SHOW_CREATE=1
2017-12-07T07:32:25.143872Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.143972Z 40 Query show create table t1
2017-12-07T07:32:25.144064Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.144154Z 40 Query show fields from t1
2017-12-07T07:32:25.144543Z 40 Query show fields from t1
2017-12-07T07:32:25.144951Z 40 Query SELECT /!40001 SQL_NO_CACHE / FROM t1
2017-12-07T07:32:25.145135Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.145207Z 40 Query use yhtest
2017-12-07T07:32:25.145282Z 40 Query select @@collation_database
2017-12-07T07:32:25.145366Z 40 Query SHOW TRIGGERS LIKE 't1'
2017-12-07T07:32:25.145668Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.145740Z 40 Query ROLLBACK TO SAVEPOINT sp
2017-12-07T07:32:25.145813Z 40 Query show table status like 't122'
2017-12-07T07:32:25.146389Z 40 Query SET SQL_QUOTE_SHOW_CREATE=1
2017-12-07T07:32:25.146464Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.146533Z 40 Query show create table t122
2017-12-07T07:32:25.146621Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.146702Z 40 Query show fields from t122
2017-12-07T07:32:25.147099Z 40 Query show fields from t122
2017-12-07T07:32:25.147395Z 40 Query SELECT /
!40001 SQL_NO_CACHE / FROM t122
2017-12-07T07:32:25.147545Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.147615Z 40 Query use yhtest
2017-12-07T07:32:25.147690Z 40 Query select @@collation_database
2017-12-07T07:32:25.147771Z 40 Query SHOW TRIGGERS LIKE 't122'
2017-12-07T07:32:25.148128Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.148201Z 40 Query ROLLBACK TO SAVEPOINT sp
2017-12-07T07:32:25.148273Z 40 Query show table status like 'yh1'
2017-12-07T07:32:25.149056Z 40 Query SET SQL_QUOTE_SHOW_CREATE=1
2017-12-07T07:32:25.149129Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.149199Z 40 Query show create table yh1
2017-12-07T07:32:25.149582Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.149665Z 40 Query show fields from yh1
2017-12-07T07:32:25.150010Z 40 Query show fields from yh1
2017-12-07T07:32:25.150293Z 40 Query SELECT /!40001 SQL_NO_CACHE / * FROM yh1
2017-12-07T07:32:25.150443Z 40 Query SET SESSION character_set_results = 'binary'
2017-12-07T07:32:25.150513Z 40 Query use yhtest
2017-12-07T07:32:25.150587Z 40 Query select @@collation_database
2017-12-07T07:32:25.150668Z 40 Query SHOW TRIGGERS LIKE 'yh1'
2017-12-07T07:32:25.151022Z 40 Query SET SESSION character_set_results = 'utf8'
2017-12-07T07:32:25.151096Z 40 Query ROLLBACK TO SAVEPOINT sp
2017-12-07T07:32:25.151158Z 40 Query RELEASE SAVEPOINT sp
2017-12-07T07:32:25.158814Z 40 Quit

1、mysqldump

首先来看下 mysqldump 的几个主要参数的实际工作方式。

通过全量日志,我们大致可以看出mysqldump的执行过程
1可以看出dump命令链接正式进入数据库。
2 flushtables操作。该操作会将内存中缓存的表结构数据同步到磁盘中。
3做了FLUSH TABLES WITH READ LOCK操作获得一个全局锁,确保此时数据是一致的。
4将当前会话的事务隔离级别恢复成默认的RR模式,使得当前事务可重复读。
5开启一个事务,并设置成快照级别。
6查询数据库的GTID是否开启。
7获取binlog的文件名及position的位置。
8释放全局锁。
9通过select语句查询test1库的状态。
10查询一下字典。
11进入要备份的test1库。
12查看建库语句。
13创建一个事务恢复点sp。
14查看需要备份的库中都有哪些表。
15查看表T1状态。
16设置表名和列名的格式。
17设置字符集为二进制。
18查看T1的建表语句。
19设置字符集为UTF8。
20输出表的所有信息。
21查询T1中数据,如果表中数据很大,mysql会使用limit来进行分段获取。
22设置字符集为二进制。
23进入test1库。
24查看数据库的编码格式。
25查看T1表的触发器。
26设置字符集为UTF8。
27ROLLBAKC到sp事务点。
28相同操作获取test1库中的T2表数据。
29当所有数据都获取完成后释放掉事务回滚点sp。

mysqldump 几个主要选项 1. -q 

很简单,什么都不做,只是导出时加了一个 SQL_NO_CACHE 来确保不会读取缓存里的数据。

081022 17:39:33       7 Connect     [email protected] on
7 Query       /*!40100 SET @@SQL_MODE='' */
7 Init DB     yejr
7 Query       SHOW TABLES LIKE 'yejr'
7 Query       LOCK TABLES `yejr` READ /*!32311 LOCAL */
7 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
7 Query       show create table `yejr`
7 Query       show fields from `yejr`
7 Query       show table status like 'yejr'
7 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `yejr`
7 Query       UNLOCK TABLES
7 Quit

分析mysqldump过程:

2. --lock-tables

跟上面类似,不过多加了一个 READ LOCAL LOCK,该锁不会阻止读,也不会阻止新的数据插入。

081022 17:36:21       5 Connect     [email protected] on
5 Query       /*!40100 SET @@SQL_MODE='' */
5 Init DB     yejr
5 Query       SHOW TABLES LIKE 'yejr'
5 Query       LOCK TABLES `yejr` READ /*!32311 LOCAL */
5 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
5 Query       show create table `yejr`
5 Query       show fields from `yejr`
5 Query       show table status like 'yejr'
5 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `yejr`
5 Query       UNLOCK TABLES
5 Quit

  1. FLUSH /!40101 LOCAL / TABLES

    Closes all open tables, forces all tables in use to be closed, and flushes the query cache.

  2. FLUSH TABLES WITH READ LOCK

    执行flush tables操作,并加一个全局读锁,很多童鞋可能会好奇,这两个命令貌似是重复的,为什么不在第一次执行flush tables操作的时候加上锁呢?

    下面看看源码中的解释:
    /
    We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
    will wait but will not stall the whole mysqld, and when the long update is
    done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
    FLUSH TABLES is to lower the probability of a stage where both mysqldump
    and most client connections are stalled. Of course, if a second long
    update starts between the two FLUSHes, we have that bad stall.
    /
    简而言之,是为了避免较长的事务操作造成FLUSH TABLES WITH READ LOCK操作迟迟得不到锁,但同时又阻塞了其它客户端操作。

  3. SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

    设置当前会话的事务隔离等级为RR,RR可避免不可重复读和幻读。

    START TRANSACTION /!40100 WITH CONSISTENT SNAPSHOT /

    获取当前数据库的快照,这个是由mysqldump中--single-transaction决定的。我们对比下加了该参数和没加的区别,日志如下:
    有--single-transaction 参数:
    图片 4
    无--single-transaction 参数:
    图片 5
    可以看到,当我们不加参数--single-transaction 参数时,将会少了对隔级别设置,少了开启事物一致性快照,少了unlock tables;

  4. SHOW MASTER STATUS

    这个是由--master-data决定的,记录了开始备份时,binlog的状态信息,包括MASTER_LOG_FILE和MASTER_LOG_POS

  5. UNLOCK TABLES 释放锁。

3. --lock-all-tables

这个就有点不太一样了,它请求发起一个全局的读锁,会阻止对所有表的写入操作,以此来确保数据的一致性。备份完成后,该会话断开,会自动解锁。

081022 17:36:55       6 Connect     [email protected] on
6 Query       /*!40100 SET @@SQL_MODE='' */
6 Query       FLUSH TABLES
6 Query       FLUSH TABLES WITH READ LOCK
6 Init DB     yejr
6 Query       SHOW TABLES LIKE 'yejr'
6 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
6 Query       show create table `yejr`
6 Query       show fields from `yejr`
6 Query       show table status like 'yejr'
6 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `yejr`
6 Quit

在备份过程中还有一个操作,设置保存点, 其实,这样做不会因为元数据锁阻塞在备份期间对已经备份表的ddl操作。
/ ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata
lock on table which was already dumped. This allows to avoid blocking
concurrent DDL on this table without sacrificing correctness, as we
won't access table second time and dumps created by --single-transaction
mode have validity point at the start of transaction anyway.
Note that this doesn't make --single-transaction mode with concurrent
DDL safe in general case. It just improves situation for people for whom
it might be working.* /

4. --master-data

除了和刚才的 --lock-all-tables 多了个 SHOW MASTER STATUS 之外,没有别的变化。

081022 17:59:02       1 Connect     [email protected] on
1 Query       /*!40100 SET @@SQL_MODE='' */
1 Query       FLUSH TABLES
1 Query       FLUSH TABLES WITH READ LOCK
1 Query       SHOW MASTER STATUS
1 Init DB     yejr
1 Query       SHOW TABLES LIKE 'yejr'
1 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
1 Query       show create table `yejr`
1 Query       show fields from `yejr`
1 Query       show table status like 'yejr'
1 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `yejr`
1 Quit

  1. --single-transaction

InnoDB 表在备份时,通常启用选项 --single-transaction 来保证备份的一致性,实际上它的工作原理是设定本次会话的隔离级别为:REPEATABLE READ,以确保本次会话(dump)时,不会看到其他会话已经提交了的数据。

081022 17:23:35       1 Connect     [email protected] on
1 Query       /*!40100 SET @@SQL_MODE='' */
1 Query       SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
1 Query       BEGIN
1 Query       UNLOCK TABLES
1 Init DB     yejr
1 Query       SHOW TABLES LIKE 'yejr'
1 Query       SET OPTION SQL_QUOTE_SHOW_CREATE=1
1 Query       show create table `yejr`
1 Query       show fields from `yejr`
1 Query       show table status like 'yejr'
1 Query       SELECT /*!40001 SQL_NO_CACHE */ * FROM `yejr`
1 Quit
  1. --single-transaction and --master-data
    本例中,由于增加了选项 --master-data,因此还需要提交一个快速的全局读锁。在这里,可以看到和上面的不同之处在于少了发起 BEGIN 来显式声明事务的开始。这里采用 START TRANSACTION WITH CONSISTENT SNAPSHOT 来代替 BEGIN 的做法的缘故不是太了解,可以看看源代码来分析下。

    081022 17:27:07 2 Connect [email protected] on 2 Query /!40100 SET @@SQL_MODE='' / 2 Query FLUSH TABLES 2 Query FLUSH TABLES WITH READ LOCK 2 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ 2 Query START TRANSACTION WITH CONSISTENT SNAPSHOT 2 Query SHOW MASTER STATUS 2 Query UNLOCK TABLES 2 Init DB yejr 2 Query SHOW TABLES LIKE 'yejr' 2 Query SET OPTION SQL_QUOTE_SHOW_CREATE=1 2 Query show create table yejr 2 Query show fields from yejr 2 Query show table status like 'yejr' 2 Query SELECT /!40001 SQL_NO_CACHE / * FROM yejr 2 Quit

关于隔离级别可以看手册 13.2.10.3. InnoDB and TRANSACTION ISOLATION LEVEL,或者本站之前的文章:[InnoDB系列] - 实例解析Innodb的隔离级别以及锁模式。

关于 START TRANSACTION WITH CONSISTENT SNAPSHOT 的说明可以看下手册描述:

The WITH CONSISTENT SNAPSHOT clause starts a consistent read for storage engines that are capable of it. This applies only to InnoDB. The effect is the same as issuing a START TRANSACTION followed by a SELECT from any InnoDB  table. See Section 13.2.10.4, “Consistent Non-Locking Read”. The WITH CONSISTENT SNAPSHOT clause does not change the current transaction isolation level, so it provides a consistent snapshot only if the current isolation level is one that allows consistent read (REPEATABLE READ or SERIALIZABLE).

12.4.1. START TRANSACTION, COMMIT, and ROLLBACK Syntax

模仿这个步骤测试一下

2. mysqldump 和 mk-parralel-dump 的比较

mk-parralel-dump 是开源项目 Maatkit 中的一个工具,主要由 Baron Schwartz 维护。
mk-parralel-dump 是由 perl 开发的,可以实现并发的导出数据表。具体的功能不细说,自己去看相关文档吧。这里只列出在我的环境下和 mysqldump 的对比数据。

测试1:
隔离级别 RR模式,开启一个会话A执行如下操作:
图片 6
开启一个会话B执行如下操作:
图片 7
开启一个会话C 查看状态,show processlist
图片 8
我们可以看到,这样B会话是会被A会话元数据所阻塞的,这个时候,如果在有其他会话访问t1 表,同样会被B会话阻塞!

2.1 mysqldump 常规使用

#导出耗时
time mysqldump -f --single-transaction -B yejr --tables yejr | gzip > /home/databak/yejr.sql.gz
real    10m15.319s
user    6m47.946s
sys     0m38.496s
#文件大小
608M /home/databak/yejr.sql.gz
#导出期间系统负载
05:00:01 PM       all      0.71      0.00      0.61      7.33     91.36
05:10:02 PM       all     13.93      0.00      2.21      4.64     79.22

测试2

2.2 mysqldump + gzip --fast

#导出耗时
time mysqldump -f --single-transaction -B yejr --tables yejr | gzip --fast > /home/databak/yejr_fast.sql.gz
real    9m6.248s
user    4m21.467s
sys     0m37.604s
#文件大小
815M Oct 21 17:33 /home/databak/yejr_fast.sql.gz
#导出期间系统负载
05:20:01 PM       all     11.94      0.00      2.43      5.69     79.94
05:30:01 PM       all      6.46      0.00      1.57      3.95     88.02

在A会话执行如下操作:
图片 9
在B会话执行
图片 10
我们看到B会话的DDL操作是可以执行成功的。
在A会话执行 如下操作
图片 11
在B会话执行
图片 12
B会话也是可以执行成功的。

2.3 mk-parallel-dump 常规使用

time ./mk-parallel-dump --database yejr --tables yejr --basedir /home/databak/
default:             25 tables,    25 chunks,    25 successes,  0 failures, 404.93 wall-clock time, 613.25 dump time
real    6m48.763s
user    4m20.724s
sys     0m38.125s
#文件大小
819M    /home/databak/default/yejr/
#导出期间系统负载
05:10:02 PM       all     13.93      0.00      2.21      4.64     79.22
05:20:01 PM       all     11.94      0.00      2.43      5.69     79.94

可以看到,mk-parallel-dump 尽快确实实现了并发导出,速度相对快多了,却有个致命伤:那就是它不支持InnoDB的一致性备份,目前已经有人提交相关代码了,不过还没实现,期待中。

: [email protected]),来源: 0、前言 本...

测试三:
A会话执行如下操作:
图片 13
B会话执行
图片 14
这个时候我们看出B会话被A会话阻塞,通过show processlist; 也可以看出B会话等待元数据锁,
我们在A会话跑 rollback to SAVEPOINT sp;
图片 15
这个时候我们看到 B会话执行成功了
图片 16
通过 SAVEPOINT sp; 设置保存点,通过rollback to SAVEPOINT sp; 相当于在select 完成后,立即释放了该表的元数据锁,而不会等到本次会话提交,这样可以避免DDL长时间无法获得元数据锁,从而导致该表的其他查询操作等待。
从这三个测试我们也可以看出START TRANSACTION WITH CONSISTENT SNAPSHOT开启的事务只能通过commit或者rollback来结束,而不是ROLLBACK TO SAVEPOINT sp。
需要注意的是,如果 alter table 发生在select from t1 之前,也就是第二种测试情况,DDL是可以提交成功的,那么我们再进行 select from t1 查询的时候,是会报错的,
图片 17
发生在备份中,同样会报错!
总结:
至此,我们可以总结下mysqldump的备份原理:通过设置READ LOCK获取数据库全局锁后,RR事务隔离级别下记录当前的日志文件名和日志位置position,然后释放掉全局锁。接下来创建一个事务的回滚点,所有数据的获取都是获取的是这个sp回滚点数据。最后释放掉回滚点sp。当然,对于MyISAM存储引擎,备份是直接锁全表的。
值得注意点:从分析mysqldump过程中我们可以知道,此命令在开始时刻会带来数据库瞬时的锁定(FLUSHTABLES WITH READ LOCK),虽然锁定时间是非常短暂的,但是却会带来非常大的数据库隐患,因为在此过程中,如果执行有DDL语句,就会导致此命令堵塞并最终异常退出。所以在做备份时间节点的选择上,需要根据数据库环境选择在负载压力最小,且没有以上操作时候进行备份。

  1. mysqldump的本质是通过select * from tab来获取表的数据的。

    1. mysqldump只适合放到业务低峰期做,如果备份的过程中数据操作很频繁,会造成Undo表空间越来越大,undo表空间默认是放到共享表空间中的,而ibdata的特性是一旦增大,就不会收缩。
  2. mysqldump的效率还是比较低下,START TRANSACTION /!40100 WITH CONSISTENT SNAPSHOT /只能等到所有表备份完后才结束,其实效率比较高的做法是备份完一张表就提交一次,这样可尽快释放Undo表空间快照占用的空间。但这样做,就无法实现对所有表的一致性备份。

  3. 为什么备份完成后没有commit操作

    /*
    No reason to explicitely COMMIT the transaction, neither to explicitely
    UNLOCK TABLES: these will be automatically be done by the server when we
    disconnect now. Saves some code here, some network trips, adds nothing to
    server.

    */

本文由大发体育娱乐在线发布于关于计算机,转载请注明出处:mysql逻辑备份,深入理解MySQL系列

关键词:

最火资讯