我可以通过复制文件来复制MySQL数据库吗?这些文件到底包含什么?

我可以通过复制文件来复制MySQL数据库吗?这些文件到底包含什么?

我正在使用 MySQL 数据库和 Ubuntu Linux 机器。

我的数据库名为db_test,我注意到路径下/var/lib/mysql/db_test有一些后缀为.frm,的文件.MYD.MYI如下所示:

/var/lib/mysql/db_test# ls

cars.frm 
cars.MYD 
cars.MYI

customers.frm
customers.MYD
customers.MYI

departments.frm
departments.MYD
departments.MYI

... 

似乎每个.frm, .MYD,.MYI文件组都映射到数据库中的一个表。

我有以下两个问题要问:

  1. 这三个文件到底在做什么?

  2. 如果我在路径/var/lib/mysql/say下创建一个新目录db_test_2,并将db_test_1目录中的每个文件复制到db_test_2,它还会创建一个db_test_2与 的内容(表)完全相同的新数据库db_test_1吗?

此物理数据库文件移动操作是否会产生与以下命令行操作相同的结果:

  1. db_test_1转储数据库

  2. 创建一个新数据库db_test_2

  3. 然后将db_test_1数据库转储回新数据库db_test_2

mysqldump如果是这样,那么移动文件似乎比复制数据库(或将数据从 MySQL 中的一个数据库导入到另一个数据库)要快得多。对此有何意见?

答案1

  1. AFAIR,.frm 是描述文件(其中描述数据库表结构),.MYD 是包含数据的文件,.MYI 是包含索引的文件。

  2. 是的,复制会快得多。但有一个问题:它不是原子的。在高负载下,复制的文件将不一致,甚至可能根本损坏。特别是如果您使用一些更“智能”的引擎(例如 InnoDB)。

编辑:ps 你可以安全地复制这些文件,但之前你应该停止mysql服务器。

答案2

您有一个命令行工具可以执行以下操作:mysqlhotcopy

它适用于 myisam 表,但不适用于 InnoDb 表。

如果您已经使用 lvm 配置了服务器,并将 /var/lib/mysql 放在专用卷上,那么我建议您以非阻塞方式快速备份所有数据库:

mysql -U root -p
  > flush tables with read lock;

这会将所有表刷新到磁盘并阻止任何读/写操作

  > system "lvcreate -s -L 1G -n lvMysql_snap /dev/vg_myserver/lv_mysql" ;

需要适应您的配置,这会创建数据库文件系统的快照。不需要时间

  > unlock tables;

完成后,R/W 操作恢复。

现在您可以挂载 /dev/vg_myserver/lvMysql_snap 并为您的数据库创建 tar 存档!

答案3

这适用于 MyISAM,但不适用于 InnoDB。看https://serverfault.com/a/367321/57569

从这个答案来看,关于 InnoDB:

如果您只想复制 .frm 和 .ibd 文件,那么您将陷入痛苦的境地。仅当您可以保证 .ibd 文件的表空间 ID 与 ibdata1 文件的元数据中的表空间 ID 条目完全匹配时,复制 InnoDB 表的 .frm 和 .ibd 文件才是有效的。

答案4

我发现mysqldump | mysql即使在同一台机器/mysql服务器上克隆 6GB 数据库的方法也太慢,所以我尝试复制数据库的整个 datadir 文件夹,并尝试将其粘贴到其他数据库的不同文件夹(同一实例)上,我可以在其中搞乱它。事实证明,启动 mysql 时它似乎已损坏。尝试设置 auto_recover 表,但没有成功。

我猜它只适用于相同的数据库名称。我所做的是创建 2 个运行 mysql 的 docker 容器,其中 1 个作为我的生产从属的从属容器,一个用于通过 docker 映射文件直接复制。请参阅下面的我的结构。

          +-----------+
          | Master DB |
          +-----------+
                |
 (Replication)  |
        +-----------------+
        | Slave/Master DB |
        +-----------------+
                |
                |         Cloud / Production Server
                V
======================================================================
                |
                |         My Local Computer
 (Replication)  |
          +-----------+    - Docker Container: AppDBLive.readonly
          | Slave  DB |    - DB Name: MyAppDB
          +-----------+    - READ Only (If I want to test live data)
                |          - Consistently cloning from prod slave/master
                |
  (Rsync/Copy datadir of MyAppDB)
                |
                V
        +----------------+  - Docker Container: AppDBLive.readwrite
        | No Replication |  - DB Name: MyAppDB
        +----------------+  - Can Write and mess with all the data for testing/dev
                            - clone via sh script to trigger rsync from AppDBLive.read

这是我构建 docker 容器的脚本:

/local/path/to/AppDBLive.readonly/run.sh:

_PWD=`pwd`
docker run --name=MyAppDB \
--mount type=bind,src=$_PWD/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=$_PWD/datadir,dst=/var/lib/mysql \
--mount type=bind,src=$_PWD/logs,dst=/var/log/mysql \
-p 3336:3306 \
-d mysql/mysql-server:5.7

/local/path/to/AppDBLive.readwrite/run.sh:

_PWD=`pwd`
docker run --name=MyAppDB.dev \
--mount type=bind,src=$_PWD/my.cnf,dst=/etc/my.cnf \
--mount type=bind,src=$_PWD/datadir,dst=/var/lib/mysql \
--mount type=bind,src=$_PWD/logs,dst=/var/log/mysql \
-p 3337:3306 \
-d mysql/mysql-server:5.7

请注意两个容器端口号的差异。确保您的应用程序连接到正确的端口。

还要确保当您运行克隆脚本时,两个容器都已关闭。

相关内容