MyISAM过去很方便地将每个表存储在相应的文件中。 InnoDB在许多方面都取得了进步,但是我不知道为什么InnoDB将所有数据库存储在一个文件中(默认情况下为ibdata1)。

我了解InnoDB会按单个索引文件映射文件中数据的位置表,但我不明白为什么将所有数据混合在一个文件中。更重要的是,为什么要混合服务器上所有数据库的数据?

MyISAM的一个有趣功能是可以将数据库文件夹复制/粘贴到另一台计算机上,然后使用数据库(无需转储)。 )。

#1 楼

InnoDB的体系结构要求使用四种基本类型的信息页

表数据页
表索引页
表元数据

MVCC数据(以支持事务隔离和ACID符合性)

回滚段
撤消空间
双重写入缓冲区(后台写入以防止依赖于OS缓存)
插入缓冲区(管理更改)非唯一的二级索引)




请参见ibdata1的图片表示形式
默认情况下,innodb_file_per_table被禁用。这将导致所有四种信息页面类型都进入一个名为ibdata1的文件。许多人试图通过制作多个ibdata文件来分散数据。这可能会导致数据和索引页的碎片化。
这就是为什么我通常建议使用默认的ibdata1文件清理InnoDB基础结构,而仅此而已。
由于存在基础结构,因此复制非常危险InnoDB有效。有两种基本的基础结构

禁用innodb_file_per_table

启用innodb_file_per_table

InnoDB(禁用innodb_file_per_table)
禁用innodb_file_per_table时,所有这些类型的InnoDB信息都将存在于其中ibdata1。 ibdata1之外的任何InnoDB表的唯一表现是InnoDB表的.frm文件。一次复制所有InnoDB数据需要复制所有/ var / lib / mysql。
复制单个InnoDB表是完全不可能的。您必须使用MySQL dump来提取表的转储,以作为数据及其对应的索引定义的逻辑表示。然后,您可以将该转储加载到同一服务器或另一台服务器上的另一个数据库中。
InnoDB(启用innodb_file_per_table)
启用innodb_file_per_table时,表数据及其索引位于.frm文件旁边的数据库文件夹中。 。例如,对于表db1.mytable,该InnoDB表在ibdata1之外的表现为:

/var/lib/mysql/db1/mytable.frm
/var/lib/mysql/db1/mytable.ibd

系统表空间ibdata1

db1.mytable的所有元数据仍然驻留在ibdata1中,并且绝对没有办法解决。重做日志和MVCC数据也仍然与ibdata1一起使用。
当涉及表碎片时,ibdata1会发生以下情况:


启用innodb_file_per_table:您可以收缩db1.mytables与ALTER TABLE db1.mytable ENGINE=InnoDB;OPTIMIZE TABLE db1.mytable;一起使用。这导致/var/lib/mysql/db1/mytable.ibd在物理上较小,并且没有碎片。

innodb_file_per_table禁用:您不能使用ALTER TABLE db1.mytable ENGINE=InnoDB;OPTIMIZE TABLE db1.mytable;收缩db1.mytables,因为它驻留在ibdata1中。实际上运行这两个命令,可使表连续且读写更快。不幸的是,这发生在ibdata1的末尾。这使ibdata1快速增长。这在我的InnoDB清理文章中已得到完全解决。 ,您正处在痛苦的世界中。仅当且仅当您可以确保.ibd文件的表空间ID与ibdata1文件的元数据中的表空间ID条目完全匹配时,才可以复制InnoDB表的.frm和.ibd文件。
我在DBA StackExchange中写了两篇有关此表空间ID概念的文章。


InnoDB中的表压缩? (在“恢复数据库”标题下)
如何恢复文件已移动的InnoDB表

这里是有关如何将任何.ibd文件重新附加到ibdata1的绝佳链接。不匹配的表空间ID:http://www.chriscalender.com/?tag=innodb-error-tablespace-id-in-file。阅读完此内容后,您应该立即意识到复制.ibd文件简直是疯了。
对于InnoDB,您只需要移动一下内容即可。 InnoDB表。
如果要将其迁移到另一个数据库服务器,请使用mysqldump。
关于混合所有数据库中的所有InnoDB表,我实际上可以看到这样做的智慧。在我的雇主的DB / Web托管公司中,我有一个MySQL客户端,该客户端在一个数据库中具有一个表,该表的约束映射到同一MySQL实例中另一个数据库中的另一个表。通过一个通用的元数据存储库,它使得跨多个数据库的事务支持和MVCC可操作性成为可能。

评论


这是否意味着当我为每个启用的表使用innodb文件时,并且如果我需要将数据从一台服务器导入到另一台服务器,则仅需使用mysqldump而不使用任何其他工具(如Percona xtrabackup)?

–tesla747
16年8月30日在14:07

#2 楼

您可以通过将innodb-file-per-table添加到cnf中来切换InnoDB以按文件存储表。

Innodb实际上只关心基本数据页面。实际上,您可以将InnoDB设置为仅使用没有文件系统的原始块设备! http://dev.mysql.com/doc/refman/5.5/zh-CN/innodb-raw-devices.html

存储文件的表很方便,例如可以更轻松地重新使用通过优化实现空间。

即使每个表都有文件,您也不能如此轻松地复制ibd文件,因为InnoDB是事务性的,并将有关其状态的信息存储在全局共享的ibdata / log文件中。 br />
那不是说不能做。如果表处于脱机状态,则可以丢弃/导入表空间,并在http://dev.mysql.com/doc/refman/5.5/en/innodb-multiple-tablespaces.html
周围复制.idbs。

评论


毫无疑问,InnoDB是一种灵活的引擎,但是我不明白将所有数据存储在一个文件中有何好处(因为与MyISAM相比,这种新结构已在InnoDB中实现了)。

– Googlebot
2012-03-25 15:46

我认为,事后诸葛亮之一是20/20。在innodb首次推出后,添加了“每表文件”选项。除了提供它自己的块设备来避免文件系统开销之外,我无法提供将它们全部一起转储更好的原因(整个块设备的问题在于它自己争论)。我所有的innodb设置都启用了每个表的文件。

– atxdba
2012年3月25日15:52



重点在于,不依赖文件系统可能是无价之宝,但默认情况下它不处于活动状态。因此,一些用户将使用它。

– Googlebot
2012年3月25日16:11

如果您有很多表而没有太多RAM,则每个表一个文件选项可能会造成危害(例如,Magento商店可能有约1000个表)。并且打开文件的设置也必须进行优化(考虑到操作系统的限制)。因此,请谨慎使用。

–超立方体ᵀᴹ
2012年3月25日16:31

当然,它可以阻碍恢复工作。是的,您应该有一个备份,但是如果没有,InnoDB会因为这种结构而使事情变得更难。

–mikato
2015年10月6日14:43

#3 楼

这是默认行为,但不是强制性的。从MySQL文档开始,使用每表表空间:

默认情况下,所有InnoDB表和索引都存储在系统表空间中。或者,您可以将每个InnoDB表及其索引存储在其自己的文件中。此功能称为“多个表空间”,因为在此设置生效时创建的每个表都有其自己的表空间。

为什么,原因可能是两个引擎的架构不同(MyISAM和InnoDB)。例如,在InnoDB中,您不能仅将.ibd文件复制到另一个数据库或安装中。说明(在同一页面上):.ibd文件的可移植性注意事项
您无法像MyISAM表文件一样在数据库目录之间自由移动.ibd文件。存储在InnoDB共享表空间中的表定义包括数据库名称。表空间文件中存储的事务ID和日志序列号在数据库之间也不同。


评论


很有帮助的答案并澄清了问题,但我仍然很好奇包含所有数据库的大文件如何提高性能(如果可以)。

– Googlebot
2012-03-25 15:42

由于所有文件只有一个,因此性能并不好。各种特性(例如行级锁定而不是表级)有助于提高性能。当然,主要优势是事务和FK约束(以及数据库的完整性)。

–超立方体ᵀᴹ
2012-03-25 16:16



您完全正确!我知道为什么最好将数据库的所有表放在一个singe文件中;但是我不明白为什么要将所有数据库(完全独立)放在同一个文件中。默认情况下,InnoDB仅使用一个文件来存储数据。

– Googlebot
2012年3月25日16:50