目录
InnoDB
是一种平衡高可靠性和高性能的通用存储引擎。
在MySQL 8.0中,
InnoDB
是默认的MySQL存储引擎。
除非您配置了不同的默认存储引擎,否则发出
CREATE
TABLE
不带
ENGINE=
子句的语句会创建
InnoDB
表。
它的 DML 操作遵循 ACID 模型, 具有 提交 , 回滚 和 崩溃恢复 功能的 事务 来保护用户数据。 有关 更多信息 , 请参见 第15.2节“InnoDB和ACID模型” 。
行级 锁定 和Oracle风格的 一致性读取可 提高多用户并发性和性能。 有关 更多信息 , 请参见 第15.7节“InnoDB锁定和事务模型” 。
InnoDB
表格将您的数据排列在磁盘上,以根据
主键
优化查询
。
每个
InnoDB
表都有一个称为
聚簇索引
的主键索引
,用于组织数据以最小化主键查找的I / O.
有关
更多信息
,
请参见
第15.6.2.1节“聚簇和二级索引”
。
要保持数据
完整性
,请
InnoDB
支持
FOREIGN
KEY
约束。
使用外键,将检查插入,更新和删除,以确保它们不会导致不同表之间的不一致。
有关
更多信息
,
请参见
第15.6.1.5节“InnoDB和FOREIGN KEY约束”
。
表15.1 InnoDB存储引擎功能
特征 | 支持 |
---|---|
B树索引 | 是 |
备份/时间点恢复 (在服务器中实现,而不是在存储引擎中实现。) | 是 |
群集数据库支持 | 没有 |
聚集索引 | 是 |
压缩数据 | 是 |
数据缓存 | 是 |
加密数据 | 是(通过加密功能在服务器中实现;在MySQL 5.7及更高版本中,支持静态数据表空间加密。) |
外键支持 | 是 |
全文搜索索引 | 是(在MySQL 5.6及更高版本中可以使用InnoDB对FULLTEXT索引的支持。) |
地理空间数据类型支持 | 是 |
地理空间索引支持 | 是(在MySQL 5.7及更高版本中可以使用InnoDB对地理空间索引的支持。) |
哈希索引 | 否(InnoDB在内部利用哈希索引来实现其自适应哈希索引功能。) |
索引缓存 | 是 |
锁定粒度 | 行 |
MVCC | 是 |
复制支持 (在服务器中实现,而不是在存储引擎中实现。) | 是 |
存储限制 | 64TB |
T树索引 | 没有 |
交易 | 是 |
更新数据字典的统计信息 | 是 |
要比较
InnoDB
MySQL提供的其他存储引擎
的功能
,请参阅
第16章
备用存储引擎中
的
存储引擎功能
表
。
有关
InnoDB
增强功能和新功能的信息,请参阅:
第1.4节“MySQL 8.0中的新
InnoDB
功能”中
的
增强功能列表
。
该 发行说明 。
有关
InnoDB
相关术语和定义,请参阅
MySQL词汇表
。
对于专用于
InnoDB
存储引擎的
论坛
,请参阅
MySQL论坛:: InnoDB
。
InnoDB
以与MySQL相同的GNU GPL许可证版本2(1991年6月)发布。
有关MySQL许可的更多信息,请
访问http://www.mysql.com/company/legal/licensing/
。
您可能会发现有
InnoDB
利于以下原因的表:
如果您的服务器因硬件或软件问题而崩溃,无论当时数据库中发生了什么,您都无需在重新启动数据库后执行任何特殊操作。
InnoDB
崩溃恢复会
自动完成在崩溃之前提交的所有更改,并撤消正在进行但未提交的任何更改。
只需重新启动并继续您离开的地方。
该
InnoDB
存储引擎维护它自己的
缓冲池
,当数据被访问主内存中缓存表和索引数据。
经常使用的数据直接从内存中处理。
此缓存适用于许多类型的信息并加快处理速度。
在专用数据库服务器上,通常会将最多80%的物理内存分配给缓冲池。
如果将相关数据拆分到不同的表中,则可以设置 强制 引用完整性的 外键 。 更新或删除数据,并自动更新或删除其他表中的相关数据。 尝试将数据插入到辅助表中,而不在主表中显示相应的数据,并且坏数据会自动被踢出。
如果数据在磁盘或内存中损坏, 校验和 机制会在您使用之前提醒您伪造数据。
使用
每个表的
相应
主键
列
设计数据库时
,将自动优化涉及这些列的操作。
引用
WHERE
子句,
ORDER
BY
子句,
GROUP BY
子句和
连接
操作中
的主键列非常快
。
插入,更新和删除通过称为
更改缓冲
的自动机制进行优化
。
InnoDB
不仅允许对同一个表进行并发读写访问,还可以缓存已更改的数据以简化磁盘I / O.
性能优势不仅限于具有长时间运行查询的巨型表。 当从表中反复访问相同的行时,称为 自适应哈希索引的功能 会接管以使这些查找更快,就像它们来自哈希表一样。
您可以压缩表和关联的索引。
您可以创建和删除索引,而对性能和可用性的影响要小得多。
截断
每个表
的
文件表
空间非常快,并且可以释放磁盘空间以供操作系统重用,而不是释放
系统表空间
中只能
InnoDB
重用的
空间
。
您可以通过查询 INFORMATION_SCHEMA 表 来监视存储引擎的内部工作方式 。
您可以通过查询 性能架构 表 来监控存储引擎的性能详细信息 。
您可以自由地将
InnoDB
表与来自其他MySQL存储引擎的表
混合
,甚至可以在同一语句中。
例如,您可以使用
连接
操作来组合
单个查询中的
数据
InnoDB
和
MEMORY
表。
InnoDB
专为处理大量数据时的CPU效率和最高性能而设计。
InnoDB
表可以处理大量数据,即使在文件大小限制为2GB的操作系统上也是如此。
对于
InnoDB
您可以在应用程序代码中应用特异性调节技术,请参阅
第8.5节,“优化InnoDB表”
。
本节介绍使用
InnoDB
表
时的最佳实践
。
根据来自这些表的相同ID值从多个表中提取数据的位置 使用 连接 。 要获得快速连接性能,请 在连接列上 定义 外键 ,并在每个表中声明具有相同数据类型的列。 添加外键可确保对引用的列建立索引,从而提高性能。 外键还会将删除或更新传播到所有受影响的表,如果父表中不存在相应的ID,则会阻止在子表中插入数据。
关闭 自动提交 。 每秒承诺数百次会限制性能(受存储设备写入速度的限制)。
分组组相关的
DML
操作成
交易
,通过包围他们
START TRANSACTION
和
COMMIT
报表。
虽然你不想过于频繁地提交,你也不想发出的巨大的批次
INSERT
,
UPDATE
或者
DELETE
,如果没有犯了几个小时运行的语句。
不使用
LOCK TABLES
语句。
InnoDB
可以同时处理多个会话,同时读取和写入同一个表,而不会牺牲可靠性或高性能。
要获得对一组行的独占写访问权,请使用
SELECT
... FOR UPDATE
语法仅锁定要更新的行。
启用该
innodb_file_per_table
选项或使用通用表空间将表的数据和索引放入单独的文件中,而不是
系统表空间
。
innodb_file_per_table
默认情况下启用
该
选项。
评估您的数据和访问模式是否受益于
InnoDB
表或页面
压缩
功能。
您可以在
InnoDB
不牺牲读/写功能的情况下
压缩
表。
使用选项运行服务器,
--sql_mode=NO_ENGINE_SUBSTITUTION
以防止在使用
ENGINE=
子句中
指定的引擎出现问题时使用其他存储引擎创建表
CREATE TABLE
。
发出
SHOW
ENGINES
语句以查看可用的MySQL存储引擎。
寻找
DEFAULT
在
InnoDB
行。
mysql> SHOW ENGINES;
或者,查询
INFORMATION_SCHEMA.ENGINES
表。
mysql> SELECT * FROM INFORMATION_SCHEMA.ENGINES;
如果
InnoDB
不是您的默认存储引擎,则可以
InnoDB
通过
--default-storage-engine=InnoDB
在命令行中定义
的服务器重新启动服务器
或
default-storage-engine=innodb
在
[mysqld]
MySQL服务器选项文件
的
部分中
定义
来确定数据库服务器或应用程序是否正常工作
。
由于更改默认存储引擎仅会在创建新表时影响新表,因此请运行所有应用程序安装和设置步骤,以确认所有内容都已正确安装。
然后练习所有应用程序功能,以确保所有数据加载,编辑和查询功能都能正常工作。
如果表依赖于特定于另一个存储引擎的功能,您将收到错误;
将该
子句
添加
到
语句中以避免错误。
ENGINE=
other_engine_name
CREATE TABLE
如果您没有对存储引擎做出深思熟虑的决定,并且想要预览某些表在使用时创建的工作方式
InnoDB
,请
ALTER
TABLE
table_name ENGINE=InnoDB;
为每个表
发出命令
。
或者,要在不打扰原始表的情况下运行测试查询和其他语句,请复制:
CREATE TABLE InnoDB_Table(...)ENGINE = InnoDB AS SELECT * FROM other_engine_table
;
要在实际工作负载下评估完整应用程序的性能,请安装最新的MySQL服务器并运行基准测试。
测试整个应用程序生命周期,从安装,大量使用和服务器重启。 在数据库忙于模拟电源故障时终止服务器进程,并在重新启动服务器时验证数据是否已成功恢复。
测试任何复制配置,尤其是在主服务器和从服务器上使用不同的MySQL版本和选项时。
该
ACID
模式是一组数据库设计原则强调的是,对于业务数据和关键任务应用重要的可靠性方面。
MySQL包含诸如的组件
InnoDB
存储引擎与ACID模型紧密结合,因此数据不会损坏,并且不会因软件崩溃和硬件故障等特殊情况而导致结果失真。
当您依赖符合ACID的功能时,您无需重新发明一致性检查和崩溃恢复机制。
如果您有其他软件安全措施,超可靠硬件或可以容忍少量数据丢失或不一致的应用程序,您可以调整MySQL设置以交换一些ACID可靠性以获得更高的性能或吞吐量。
以下部分讨论MySQL功能(尤其是
InnoDB
存储引擎)
如何
与ACID模型的类别进行交互:
答 :原子性。
C :一致性。
我 ::隔离。
D :耐用性。
ACID模型
的
原子性
方面主要涉及
InnoDB
交易
。
相关的MySQL功能包括:
ACID模型
的
一致性
方面主要涉及内部
InnoDB
处理以保护数据免于崩溃。
相关的MySQL功能包括:
ACID模型
的
隔离
方面主要涉及
InnoDB
事务
,特别
是适用于每个事务
的
隔离级别
。
相关的MySQL功能包括:
ACID模型 的 持久性 方面涉及MySQL软件功能与您的特定硬件配置交互。 由于取决于CPU,网络和存储设备的功能的许多可能性,这方面是最复杂的提供具体指导方针。 (这些指南可能采取购买 “ 新硬件 ” 的形式 。)相关的MySQL功能包括:
InnoDB
doublewrite buffer
,由
innodb_doublewrite
配置选项
打开和关闭
。
配置选项
sync_binlog
。
配置选项
innodb_file_per_table
。
在存储设备中写入缓冲区,例如磁盘驱动器,SSD或RAID阵列。
存储设备中的电池备份缓存。
用于运行MySQL的操作系统,特别是它对
fsync()
系统调用的
支持
。
不间断电源(UPS)保护运行MySQL服务器和存储MySQL数据的所有计算机服务器和存储设备的电源。
您的备份策略,例如备份的频率和类型以及备份保留期。
对于分布式或托管数据应用程序,MySQL服务器的硬件所在的数据中心的特定特征,以及数据中心之间的网络连接。
InnoDB
是一个
多版本的存储引擎
:它保存有关已更改行的旧版本的信息,以支持并发和
回滚
等事务功能
。
此信息存储在表空间中称为
回滚段
的数据结构中(在Oracle中的类似数据结构之后)。
InnoDB
使用回滚段中的信息来执行事务回滚中所需的撤消操作。
它还使用该信息构建行的早期版本以进行
一致读取
。
在内部,
InnoDB
为数据库中存储的每一行添加三个字段。
6字节
DB_TRX_ID
字段指示插入或更新行的最后一个事务的事务标识符。
此外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为已删除。
每行还包含一个
DB_ROLL_PTR
称为滚动指针
的7字节
字段。
roll指针指向写入回滚段的撤消日志记录。
如果更新了行,则撤消日志记录包含在更新行之前重建行内容所需的信息。
一个6字节的
DB_ROW_ID
字段包含一个行ID,当插入新行时,该行ID会单调增加。
如果
InnoDB
自动生成聚簇索引,索引包含行ID值。
否则,该
DB_ROW_ID
列不会出现在任何索引中。
撤消段中的撤消日志分为插入和更新撤消日志。
只在事务回滚中才需要插入撤消日志,并且可以在事务提交后立即丢弃。
更新撤消日志也用于一致性读取,但只有在没有事务
InnoDB
已分配快照的情况下
才能丢弃它们
,在一致读取中可能需要更新撤消日志中的信息来构建数据库的早期版本行。
定期提交您的交易,包括那些只发出一致读取的交易。
否则,
InnoDB
无法从更新撤消日志中丢弃数据,并且回滚段可能会变得太大,从而填满了表空间。
回滚段中撤消日志记录的物理大小通常小于相应的插入或更新行。 您可以使用此信息计算回滚段所需的空间。
在
InnoDB
多版本控制方案中,使用SQL语句删除行时,不会立即从数据库中物理删除该行。
InnoDB
只有在丢弃为删除写入的更新撤消日志记录时,才会物理删除相应的行及其索引记录。
此删除操作称为
清除
,并且速度非常快,通常与执行删除的SQL语句的时间顺序相同。
如果你在表中以大约相同的速率插入和删除少量批次的行,则清除线程可能开始落后,并且由于所有
“
死
”
行,
表可以变得越来越大
,使得所有磁盘都受到限制慢。
在这种情况下,通过调整
innodb_max_purge_lag
系统变量
来限制新行操作,并将更多资源分配给清除线程
。
有关
更多信息
,
请参见
第15.13节“InnoDB启动选项和系统变量”
。
InnoDB
多版本并发控制(MVCC)以不同于聚簇索引的方式处理二级索引。
聚集索引中的记录就地更新,其隐藏的系统列指向可以重建早期版本记录的撤消日志条目。
与聚簇索引记录不同,二级索引记录不包含隐藏的系统列,也不会就地更新。
更新二级索引列时,旧的二级索引记录将被删除标记,插入新记录,最终清除删除标记的记录。
当二级索引记录被删除标记或二级索引页面由较新的事务更新时,
InnoDB
查找聚簇索引中的数据库记录。
在聚簇索引中,将
DB_TRX_ID
检查记录,如果在启动读取事务后修改了记录,则会从撤消日志中检索正确的记录版本。
如果二级索引记录被标记为删除或二级索引页面由较新的事务更新,
则不使用
覆盖索引
技术。
而不是从索引结构返回值,而是
InnoDB
在聚簇索引中查找记录。
但是,如果
启用
了
索引条件下推(ICP)
优化,并且
WHERE
只能使用索引中的字段来评估条件的
某些部分
,则MySQL服务器仍会将此部分
WHERE
条件下推到存储引擎,在此处使用指数。
如果未找到匹配的记录,则避免聚集索引查找。
如果找到匹配的记录,即使在删除标记的记录中,也会
InnoDB
查找聚簇索引中的记录。
下图显示了构成
InnoDB
存储引擎体系
结构的内存和磁盘结构
。
有关每种结构的信息,请参见
第15.5节“InnoDB内存中结构”
和
第15.6节“InnoDB On-Disk Structures”
。
本节介绍
InnoDB
内存中的结构和相关主题。
缓冲池是主存储器中的一个区域,用于在访问时缓存表和索引数据。 缓冲池允许直接从内存处理常用数据,从而加快处理速度。 在专用服务器上,通常会将最多80%的物理内存分配给缓冲池。
为了提高大容量读取操作的效率,缓冲池被分成 可以容纳多行的 页面 。 为了提高缓存管理的效率,缓冲池被实现为链接的页面列表; 使用 LRU 算法 的变体,很少使用的数据在缓存中老化 。
了解如何利用缓冲池将频繁访问的数据保存在内存中是MySQL调优的一个重要方面。
使用最近最少使用(LRU)算法的变体将缓冲池作为列表进行管理。 当需要空间将新页面添加到缓冲池时,最近最少使用的页面被逐出,并且新页面被添加到列表的中间。 此中点插入策略将列表视为两个子列表:
在头部, 最近访问过 的新( “ 年轻 ” )页面 的子列表
在尾部,是最近访问的旧页面的子列表
该算法保留新子列表中查询大量使用的页面。 旧子列表包含较少使用的页面; 这些页面是 驱逐的 候选人 。
默认情况下,算法操作如下:
3/8的缓冲池专用于旧子列表。
列表的中点是新子列表的尾部与旧子列表的头部相交的边界。
当
InnoDB
将页面读入缓冲池时,它最初将其插入中点(旧子列表的头部)。
可以读取页面,因为它是用户指定的操作(如SQL查询)所必需的,或者是
由自动执行的
预读
操作的
一部分
InnoDB
。
访问旧子列表中的页面使其 “ 年轻 ” ,将其移动到缓冲池的头部(新子列表的头部)。 如果因为需要而读取页面,则会立即进行第一次访问,并使页面变得年轻。 如果由于预读而读取了页面,则第一次访问不会立即发生(并且在页面被逐出之前可能根本不会发生)。
随着数据库的运行,在缓冲池的页面没有被访问的 “ 年龄 ” 通过向列表的尾部移动。 新旧子列表中的页面随着其他页面的变化而变旧。 旧子列表中的页面也会随着页面插入中点而老化。 最终,仍然未使用的页面到达旧子列表的尾部并被逐出。
默认情况下,查询读取的页面会立即移动到新的子列表中,这意味着它们会更长时间地保留在缓冲池中。
表扫描(例如为
mysqldump
操作执行,或者
SELECT
带有no
WHERE
子句的语句)可以将大量数据带入缓冲池并逐出相同数量的旧数据,即使新数据从未再次使用过。
类似地,由预读后台线程加载然后仅访问一次的页面移动到新列表的头部。
这些情况可以将经常使用的页面推送到旧的子列表中,在那里它们会被驱逐。
有关优化此行为的信息,请参见
第15.8.3.3节“使缓冲池扫描阻止”
和
第15.8.3.4节“配置InnoDB缓冲池预取(预读)”
。
InnoDB
标准监视器输出包含
BUFFER POOL AND MEMORY
有关缓冲池LRU算法操作
的
部分
中的几个字段
。
有关详细信息,请参阅
使用InnoDB标准监视器监视缓冲池
。
您可以配置缓冲池的各个方面以提高性能。
理想情况下,您可以将缓冲池的大小设置为尽可能大的值,从而为服务器上的其他进程留出足够的内存,而无需过多的分页。
缓冲池越大,
InnoDB
内存数据库
就越多
,从磁盘读取数据一次,然后在后续读取期间从内存中访问数据。
请参见
第15.8.3.1节“配置InnoDB缓冲池大小”
。
在具有足够内存的64位系统上,您可以将缓冲池拆分为多个部分,以最大限度地减少并发操作之间内存结构的争用。 有关详细信息,请参见 第15.8.3.2节“配置多个缓冲池实例” 。
您可以将频繁访问的数据保留在内存中,而不管操作中的活动突然出现高峰,这些操作会将大量不经常访问的数据带入缓冲池。 有关详细信息,请参见 第15.8.3.3节“使缓冲池扫描阻止” 。
您可以控制何时以及如何执行预读请求,以异步方式将页面预取到缓冲池中,以预期很快就会需要页面。 有关详细信息,请参见 第15.8.3.4节“配置InnoDB缓冲池预取(预读)” 。
您可以控制何时发生背景刷新以及是否根据工作负载动态调整刷新率。 有关详细信息,请参见 第15.8.3.5节“配置InnoDB缓冲池刷新” 。
您可以微调缓冲池刷新行为的各个方面以提高性能。 有关详细信息,请参见 第15.8.3.6节“微调InnoDB缓冲池刷新” 。
您可以配置如何
InnoDB
保留当前缓冲池状态,以避免服务器重新启动后的长时间预热。
有关详细信息,请参见
第15.8.3.7节“保存和恢复缓冲池状态”
。
InnoDB
可以使用的标准监视器输出
SHOW
ENGINE INNODB STATUS
提供有关缓冲池操作的指标。
缓冲池指标位于
标准监视器输出
BUFFER POOL AND MEMORY
部分,
InnoDB
显示类似于以下内容:
---------------------- 缓冲池和记忆 ---------------------- 分配的总大内存为2198863872 字典内存分配为776332 缓冲池大小131072 免费缓冲区124908 数据库页面5720 旧数据库页面2071 修改了db页面910 待定读数为0 待写:LRU 0,刷新列表0,单页0 页面年轻4,而不是年轻0 0.10个年轻人/秒,0.00个非年轻人/秒 页面读取197,创建5523,写入5060 0.00读/秒,190.89创建/ s,244.94写/秒 缓冲池命中率1000/1000,年轻率为0/1000没有 0/1000 页面预读0.00 / s,没有访问0.00 / s被逐出,随机读取 提前0.00 / s LRU len:5720,unzip_LRU len:0 I / O sum [0]:cur [0],解压和[0]:cur [0]
下表描述了
InnoDB
标准监视器
报告的缓冲池指标
。
InnoDB
标准监视器输出中
提供的每秒平均值
基于自
InnoDB
上次打印标准监视器输出
以来经过的时间
。
表15.2 InnoDB缓冲池度量标准
名称 | 描述 |
---|---|
分配的总内存 | 为缓冲池分配的总内存(以字节为单位)。 |
分配的字典内存 |
为
InnoDB
数据字典
分配的总内存(
以字节为单位)。
|
缓冲池大小 | 分配给缓冲池的页面的总大小。 |
免费缓冲 | 缓冲池空闲列表的页面总大小。 |
数据库页面 | 缓冲池LRU列表的页面总大小。 |
旧数据库页面 | 缓冲池旧LRU子列表的页面总大小。 |
修改了db页面 | 缓冲池中修改的当前页数。 |
待读 | 等待读入缓冲池的缓冲池页数。 |
待写LRU | 要从LRU列表底部写入的缓冲池中的旧脏页数。 |
待处理写入刷新列表 | 在检查点期间要刷新的缓冲池页数。 |
待写单页 | 缓冲池中挂起的独立页面写入次数。 |
页面变得年轻 | 缓冲池LRU列表中的年轻页总数(移动到 “ 新 ” 页面 的子列表的头部 )。 |
页面不年轻 | 缓冲池LRU列表中未完成的页面总数(保留在 “ 旧 ” 子列表 中的页面, 而不是年轻)。 |
扬斯/秒 | 在缓冲池LRU列表中对旧页面的每秒平均访问次数导致页面变得年轻。 有关详细信息,请参阅此表后面的注释。 |
非杨氏/ s的 | 在缓冲池LRU列表中对旧页面的每秒平均访问次数导致不使页面变得年轻。 有关详细信息,请参阅此表后面的注释。 |
页面已读 | 从缓冲池中读取的总页数。 |
页面已创建 | 缓冲池中创建的总页数。 |
写的页面 | 从缓冲池写入的总页数。 |
读取/秒 | 每秒缓冲池页面读取的平均每秒数。 |
创建/秒 | 每秒创建的缓冲池页面的平均每秒数。 |
写入/秒 | 每秒缓冲池页面写入的平均每秒数。 |
缓冲池命中率 | 从缓冲池内存中读取的页面与从磁盘存储中读取的页面的缓冲池页面命中率。 |
年轻人 | 页面访问的平均命中率导致页面变得年轻。 有关详细信息,请参阅此表后面的注释。 |
不(年轻率) | 页面访问的平均命中率并未导致页面变得年轻。 有关详细信息,请参阅此表后面的注释。 |
页面预读 | 每秒预读操作的平均值。 |
被删除的页面无法访问 | 在没有从缓冲池访问的情况下被逐出的页面的每秒平均值。 |
随机预读 | 随机预读操作的每秒平均值。 |
LRU len | 缓冲池LRU列表的页面总大小。 |
unzip_LRU len | 缓冲池的总页面大小unzip_LRU列表。 |
I / O总和 | 访问的缓冲池LRU列表页面总数,最近50秒。 |
I / O cur | 访问的缓冲池LRU列表页面的总数。 |
I / O解压缩总和 | 访问的缓冲池unzip_LRU列表页面总数。 |
I / O解压缩 | 访问的缓冲池unzip_LRU列表页面总数。 |
备注 :
该
youngs/s
指标仅适用于旧页面。
它基于页面访问次数而不是页面数。
可以对给定页面进行多次访问,所有这些访问都被计算在内。
如果
youngs/s
在没有发生大型扫描时
看到非常低的
值,则可能需要减少延迟时间或增加用于旧子列表的缓冲池的百分比。
增加百分比使旧的子列表变大,因此该子列表中的页面需要更长的时间才能移动到尾部,这增加了再次访问这些页面并使其变得年轻的可能性。
该
non-youngs/s
指标仅适用于旧页面。
它基于页面访问次数而不是页面数。
可以对给定页面进行多次访问,所有这些访问都被计算在内。
如果
non-youngs/s
在执行大型表扫描时
没有看到更高的
值(并且
youngs/s
值
更高
),请增加延迟值。
该
young-making
速率考虑了对所有缓冲池页面的访问,而不仅仅是访问旧子列表中的页面。
的
young-making
速度和
not
速率通常不加起来的整体缓冲池命中率。
旧子列表中的页面命中会导致页面移动到新的子列表,但是新子列表中的页面命中会导致页面仅在距离头部一定距离时才移动到列表的头部。
not (young-making rate)
是由于
innodb_old_blocks_time
未被满足
定义的延迟
,或者由于新子列表中的页面命中没有导致页面被移动到头部
而导致页面访问没有导致页面年轻化的平均命中率
。
此速率考虑了对所有缓冲池页面的访问,而不仅仅是访问旧子列表中的页面。
缓冲池
服务器状态变量
和
INNODB_BUFFER_POOL_STATS
表提供了许多在
InnoDB
标准监视器输出中
找到的相同缓冲池指标
。
有关更多信息,请参见
例15.10“查询INNODB_BUFFER_POOL_STATS表”
。
更改缓冲区是一种特殊的数据结构,
当这些页面不在
缓冲池中
时
,它会更改
二级索引
页面
。
缓冲的变化,这可能导致从
,
或
当页面被加载到由其他的读操作缓冲池操作(DML),将在后面合并。
INSERT
UPDATE
DELETE
与 聚簇索引 不同 ,二级索引通常不是唯一的,并且插入二级索引的顺序相对随机。 同样,删除和更新可能会影响不在索引树中相邻的二级索引页。 当受影响的页面被其他操作读入缓冲池时,合并缓存的更改,避免了从磁盘读取二级索引页到缓冲池所需的大量随机访问I / O.
系统大部分空闲时或在慢速关闭期间运行的清除操作会定期将更新的索引页写入磁盘。 与每个值立即写入磁盘相比,清除操作可以更有效地为一系列索引值写入磁盘块。
当有许多受影响的行和许多要更新的辅助索引时,更改缓冲区合并可能需要几个小时。 在此期间,磁盘I / O会增加,这会导致磁盘绑定查询显着减慢。 提交事务后,甚至在服务器关闭并重新启动之后,更改缓冲区合并也可能继续发生( 有关更多信息 , 请参见 第15.20.2节“强制InnoDB恢复” )。
在内存中,更改缓冲区占用缓冲池的一部分。 在磁盘上,更改缓冲区是系统表空间的一部分,其中在关闭数据库服务器时缓冲索引更改。
变更缓冲区中缓存的数据类型由
innodb_change_buffering
变量控制。
有关更多信息,请参阅
配置更改缓冲
。
您还可以配置最大更改缓冲区大小。
有关更多信息,请参阅
配置更改缓冲区最大大小
。
如果索引包含降序索引列或主键包含降序索引列,则辅助索引不支持更改缓冲。
有关更改缓冲区的 常见问题解答 ,请参见 第A.15节“MySQL 8.0常见问题解答:InnoDB更改缓冲区” 。
对表执行
何时
INSERT
,
UPDATE
和
DELETE
操作
时
,
索引列的值(特别是辅助键的值)通常按未排序顺序排列,需要大量I / O才能使二级索引更新。
该
变化缓冲区
当相关缓存变为二级索引条目
页面
不在
缓冲池
,从而通过从磁盘上的页面不会立即读避免了昂贵的I / O操作。
当页面加载到缓冲池中时,将合并缓冲的更改,稍后将更新的页面刷新到磁盘。
该
InnoDB
主线程在服务器几乎空闲时以及在
慢速关闭
期间合并缓冲的更改
。
因为它可以减少磁盘读取和写入,所以更改缓冲区功能对于I / O绑定的工作负载最有价值,例如具有大量DML操作的应用程序(如批量插入)。
但是,更改缓冲区占用缓冲池的一部分,从而减少了可用于缓存数据页的内存。 如果工作集几乎适合缓冲池,或者您的表具有相对较少的二级索引,则禁用更改缓冲可能很有用。 如果工作数据集完全适合缓冲池,则更改缓冲不会产生额外开销,因为它仅适用于不在缓冲池中的页面。
您可以
InnoDB
使用
innodb_change_buffering
配置参数
控制
执行更改缓冲
的范围
。
您可以为插入,删除操作(当索引记录最初标记为删除时)和清除操作(物理删除索引记录时)启用或禁用缓冲。
更新操作是插入和删除的组合。
默认
innodb_change_buffering
值为
all
。
允许的
innodb_change_buffering
值包括:
all
默认值:缓冲区插入,删除标记操作和清除。
none
不要缓冲任何操作。
inserts
缓冲插入操作。
deletes
缓冲区删除标记操作。
changes
缓冲插入和删除标记操作。
purges
缓冲后台发生的物理删除操作。
您可以
innodb_change_buffering
在MySQL选项文件(
my.cnf
或
my.ini
)中
设置
参数,
也可以使用
SET GLOBAL
语句
动态更改
该
参数
,该
语句需要足以设置全局系统变量的权限。
请参见
第5.1.9.1节“系统变量权限”
。
更改设置会影响新操作的缓冲;
现有缓冲条目的合并不受影响。
该
innodb_change_buffer_max_size
变量允许将更改缓冲区的最大大小配置为缓冲池总大小的百分比。
默认情况下,
innodb_change_buffer_max_size
设置为25.最大设置为50。
考虑增加
innodb_change_buffer_max_size
具有大量插入,更新和删除活动的MySQL服务器,其中更改缓冲区合并无法跟上新的更改缓冲区条目,导致更改缓冲区达到其最大大小限制。
考虑
innodb_change_buffer_max_size
使用用于报告的静态数据在MySQL服务器上
减少
,或者如果更改缓冲区消耗了与缓冲池共享的太多内存空间,导致页面比预期更早地超出缓冲池。
使用代表性工作负载测试不同设置以确定最佳配置。
该
innodb_change_buffer_max_size
设置是动态的,允许在不重新启动服务器的情况下修改设置。
以下选项可用于更改缓冲区监视:
InnoDB
标准监视器输出包括更改缓冲区状态信息
要查看监视器数据,请发出
SHOW ENGINE INNODB STATUS
语句。
MySQL的> SHOW ENGINE INNODB STATUS\G
更改缓冲区状态信息位于
INSERT BUFFER AND ADAPTIVE HASH INDEX
标题
下,
并显示类似于以下内容:
------------------------------------- 插入缓冲区和自适应哈希索引 ------------------------------------- Ibuf:size 1,free list len 0,seg size 2,0合并 合并后的业务: 插入0,删除标记0,删除0 丢弃的操作: 插入0,删除标记0,删除0 散列表大小4425293,使用单元格32,节点堆有1个缓冲区 13577.57哈希搜索/ s,202.47非哈希搜索/ s
有关更多信息,请参见 第15.16.3节“InnoDB标准监视器和锁定监视器输出” 。
该
INFORMATION_SCHEMA.INNODB_METRICS
表提供了
InnoDB
标准监视器输出中的
大多数数据点
以及其他数据点。
要查看更改缓冲区指标及其各自的说明,请发出以下查询:
MySQL的> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%ibuf%'\G
有关
INNODB_METRICS
表用法信息,请参见
第15.14.6节“InnoDB INFORMATION_SCHEMA度量表”
。
该
INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
表提供有关缓冲池中每个页面的元数据,包括更改缓冲区索引和更改缓冲区位图页面。
更改缓冲区页面由标识
PAGE_TYPE
。
IBUF_INDEX
是更改缓冲区索引页
IBUF_BITMAP
的页面类型,是更改缓冲区位图页的页面类型。
查询
INNODB_BUFFER_PAGE
表可能会带来显着的性能开销。
为避免影响性能,请在测试实例上重现要调查的问题,并在测试实例上运行查询。
例如,您可以查询
INNODB_BUFFER_PAGE
表以确定大致
缓冲池页面的百分比
IBUF_INDEX
和
IBUF_BITMAP
页面
的大致数量
。
MySQL的>SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages,
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,
(SELECT ((change_buffer_pages/total_pages)*100))
AS change_buffer_page_percentage;
+ --------------------- + ------------- ------------- + ------------------ + | change_buffer_pages | total_pages | change_buffer_page_percentage | + --------------------- + ------------- ------------- + ------------------ + | 25 | 8192 | 0.3052 | + --------------------- + ------------- ------------- + ------------------ +
有关该
INNODB_BUFFER_PAGE
表
提供的其他数据的信息
,请参见
第25.39.1节“INFORMATION_SCHEMA INNODB_BUFFER_PAGE表”
。
有关相关用法信息,请参见
第15.14.5节“InnoDB INFORMATION_SCHEMA缓冲池表”
。
Performance Schema 为高级性能监视提供更改缓冲区互斥等待检测。 要查看更改缓冲区检测,请发出以下查询:
MySQL的>SELECT * FROM performance_schema.setup_instruments
WHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';
+ ------------------------------------------------- ------ + --------- + ------- + | NAME | 启用| 定时| + ------------------------------------------------- ------ + --------- + ------- + | wait / synch / mutex / innodb / ibuf_bitmap_mutex | 是的| 是的| | wait / synch / mutex / innodb / ibuf_mutex | 是的| 是的| | wait / synch / mutex / innodb / ibuf_pessimistic_insert_mutex | 是的| 是的| + ------------------------------------------------- ------ + --------- + ------- +
有关监视
InnoDB
互斥锁等待的信息,请参见
第15.15.2节“使用性能架构监视InnoDB Mutex等待”
。
自适应散列索引功能使得能够
InnoDB
在具有适当的工作负载组合和缓冲池足够内存的系统上执行更像内存数据库,而不会牺牲事务特性或可靠性。
自适应哈希索引功能由
innodb_adaptive_hash_index
变量
启用
,或在服务器启动时关闭
--skip-innodb-adaptive-hash-index
。
基于观察到的搜索模式,使用索引键的前缀构建哈希索引。 前缀可以是任何长度,并且可能只有B树中的某些值出现在哈希索引中。 哈希索引是根据需要经常访问的索引页面构建的。
如果表几乎完全适合主内存,则哈希索引可以通过启用任何元素的直接查找来加速查询,将索引值转换为一种指针。
InnoDB
有一个监视索引搜索的机制。
如果
InnoDB
通知查询可以从构建哈希索引中受益,则会自动执行此操作。
对于某些工作负载,哈希索引查找的加速大大超过了监视索引查找和维护哈希索引结构的额外工作。
在高负载(例如多个并发连接)下,对自适应哈希索引的访问有时会成为争用的来源。
查询与
LIKE
运营商和
%
通配符也往往不会受益。
对于无法从自适应哈希索引功能中受益的工作负载,将其关闭可减少不必要的性能开销。
由于很难预先预测自适应散列索引功能是否适合特定系统和工作负载,因此请考虑在启用和禁用运行基准测试时运行基准测试。
MySQL 5.6中的体系结构更改使其更适合禁用自适应哈希索引功能,而不是早期版本。
自适应哈希索引功能已分区。
每个索引都绑定到一个特定的分区,每个分区都由一个单独的锁存器保护。
分区由
innodb_adaptive_hash_index_parts
变量
控制
。
innodb_adaptive_hash_index_parts
默认情况下,
该
变量设置为8。
最大设置为512。
您可以在
输出
SEMAPHORES
部分中
监视自适应哈希索引的使用和争用
SHOW
ENGINE INNODB
STATUS
。
如果有许多线程正在等待创建的RW锁存器
btr0sea.c
,请考虑增加自适应哈希索引分区的数量或禁用自适应哈希索引功能。
有关哈希索引的性能特征的信息,请参见 第8.3.9节“B树和哈希索引的比较” 。
日志缓冲区是保存要写入磁盘上日志文件的数据的内存区域。
日志缓冲区大小由
innodb_log_buffer_size
变量
定义
。
默认大小为16MB。
日志缓冲区的内容会定期刷新到磁盘。
大型日志缓冲区使大型事务能够运行,而无需在事务提交之前将重做日志数据写入磁盘。
因此,如果您有更新,插入或删除许多行的事务,则增加日志缓冲区的大小可以节省磁盘I / O.
该
innodb_flush_log_at_trx_commit
变量控制如何写入日志缓冲区的内容并刷新到磁盘。
该
innodb_flush_log_at_timeout
变量控制日志刷新频率。
有关相关信息,请参阅 内存配置 和 第8.5.4节“优化InnoDB重做日志记录” 。
本节介绍
InnoDB
磁盘结构和相关主题。
本节介绍与
InnoDB
表
相关的主题
。
要创建
InnoDB
表,请使用该
CREATE
TABLE
语句。
CREATE TABLE t1(INT,b CHAR(20),PRIMARY KEY(a))ENGINE = InnoDB;
ENGINE=InnoDB
如果
InnoDB
定义为默认存储引擎,
则
不需要指定
子句
。
要检查默认存储引擎,请发出以下语句:
MySQL的> SELECT @@default_storage_engine;
+ -------------------------- +
| @@ default_storage_engine |
+ -------------------------- +
| InnoDB |
+ -------------------------- +
ENGINE=InnoDB
如果您计划使用
mysqldump
或复制来重放
CREATE
TABLE
默认存储引擎不在的服务器上的语句,
您仍可以使用
子句
InnoDB
。
一个
InnoDB
表及其索引可以在创建
系统表空间
,在一个
文件中,每个表
的表空间,或在
一般的表空间
。
如果
innodb_file_per_table
启用(默认值),则会
InnoDB
在单个每个表的文件表空间中隐式创建一个表。
相反,
innodb_file_per_table
禁用时,会
InnoDB
在
InnoDB
系统表空间中
隐式创建
表。
要在通用表空间中创建表,请使用
CREATE
TABLE ...
TABLESPACE
语法。
有关更多信息,请参见
第15.6.3.3节“常规表空间”
。
当您在每个表的文件表空间中创建一个
表时,默认情况下
,MySQL会
在MySQL数据目录下的数据库目录中
创建一个
.ibd
表空间文件。
在
InnoDB
系统表空间中创建的表是在现有的
ibdata文件中
创建的,该
文件
位于MySQL数据目录中。
在通用表空间中创建的表在现有的通用表空间
.ibd文件中创建
。
可以在MySQL数据目录的内部或外部创建常规表空间文件。
有关更多信息,请参见
第15.6.3.3节“常规表空间”
。
在内部,
InnoDB
将每个表的条目添加到数据字典中。
该条目包括数据库名称。
例如,如果
t1
在
test
数据库中
创建了
表,则数据库名称的数据字典条目为
'test/t1'
。
这意味着您可以
t1
在不同的数据库中
创建具有相同名称(
)的表,并且表名不会在内部发生冲突
InnoDB
。
InnoDB
表
的默认行格式
由
innodb_default_row_format
配置选项
定义
,其默认值为
DYNAMIC
。
Dynamic
和
Compressed
行格式允许您利用
InnoDB
表压缩和长列值的高效页外存储等功能。
要使用这些行格式,
innodb_file_per_table
必须启用(默认值)。
SET GLOBAL innodb_file_per_table = 1; CREATE TABLE t3(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = DYNAMIC; CREATE TABLE t4(INT,b CHAR(20),PRIMARY KEY(a))ROW_FORMAT = COMPRESSED;
或者,您可以使用
CREATE
TABLE ...
TABLESPACE
语法
InnoDB
在常规表空间中
创建
表。
常规表空间支持所有行格式。
有关更多信息,请参见
第15.6.3.3节“常规表空间”
。
CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE ts1 ROW_FORMAT = DYNAMIC;
CREATE
TABLE ...
TABLESPACE
语法还可用于
在系统表空间中
创建
InnoDB
具有
Dynamic
行格式的表,以及具有
行
Compact
或
Redundant
行格式的
表
。
CREATE TABLE t1(c1 INT PRIMARY KEY)TABLESPACE = innodb_system ROW_FORMAT = DYNAMIC;
有关
InnoDB
行格式的
更多信息
,请参见
第15.10节“InnoDB行格式”
。
有关如何确定
InnoDB
表
的行格式
和
InnoDB
行格式
的物理特性
,请参见
第15.10节“InnoDB行格式”
。
始终
为
表
定义
主键
InnoDB
,指定以下列:
被最重要的查询引用。
永远不会留空。
永远不会有重复的值。
很少,如果一旦插入就改变价值。
例如,在包含有关人员信息的表格中,您不会创建主键,
(firstname,
lastname)
因为多个人可以使用相同的名称,有些人使用空白姓氏,有时人们会更改其姓名。
由于存在如此多的约束,通常没有一组明显的列用作主键,因此您创建一个带有数字ID的新列作为主键的全部或部分。
您可以声明一个
自动增量
列,以便在插入行时自动填充升序值:
#ID的值可以像不同表中相关项之间的指针一样。 CREATE TABLE t5(id INT AUTO_INCREMENT,b CHAR(20),PRIMARY KEY(id)); #主键可以包含多个列。任何autoinc列都必须先行。 CREATE TABLE t6(id INT AUTO_INCREMENT,INT,b CHAR(20),PRIMARY KEY(id,a));
尽管该表在没有定义主键的情况下正常工作,但主键涉及性能的许多方面,并且是任何大型或经常使用的表的关键设计方面。
建议您始终在
CREATE
TABLE
语句中
指定主键
。
如果您创建表,加载数据,然后运行
ALTER
TABLE
以稍后添加主键,则该操作比创建表时定义主键要慢得多。
要查看
InnoDB
表
的属性
,请发出以下
SHOW TABLE STATUS
语句:
MySQL的> SHOW TABLE STATUS FROM test LIKE 't%' \G;
*************************** 1。排******************** *******
姓名:t1
引擎:InnoDB
版本:10
Row_format:紧凑
行:0
Avg_row_length:0
Data_length:16384
Max_data_length:0
Index_length:0
Data_free:0
Auto_increment:NULL
Create_time:2015-03-16 15:13:31
Update_time:NULL
Check_time:NULL
排序规则:utf8mb4_0900_ai_ci
校验和:NULL
Create_options:
评论:
有关
SHOW TABLE
STATUS
输出的
信息
,请参见
第13.7.6.36节“显示表状态语法”
。
InnoDB
也可以使用
InnoDB
Information Schema系统表
查询表属性
:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME='test/t1' \G
*************************** 1。排******************** *******
TABLE_ID:45
姓名:test / t1
标志:1
N_COLS:5
空间:35
ROW_FORMAT:紧凑
ZIP_PAGE_SIZE:0
SPACE_TYPE:单身
有关更多信息,请参见 第15.14.3节“InnoDB INFORMATION_SCHEMA架构对象表” 。
本节介绍将一些或所有
InnoDB
表
移动或复制
到其他服务器或实例的技术。
例如,您可以将整个MySQL实例移动到更大,更快的服务器;
您可以将整个MySQL实例克隆到新的复制从属服务器;
您可以将单个表复制到另一个实例以开发和测试应用程序,或者复制到数据仓库服务器以生成报告。
在Windows上,
InnoDB
始终以小写形式在内部存储数据库和表名。
要以二进制格式将数据库从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。
一种方便的方法是
在创建任何数据库或表之前将以
下行添加到
或
文件
的
[mysqld]
部分
:
my.cnf
my.ini
的[mysqld] 的lower_case_table_names = 1
禁止
lower_case_table_names
使用与初始化
服务器时使用的
设置不同的设置启动服务器。
移动或复制
InnoDB
表格的
技巧
包括:
可传输表空间功能用于
FLUSH
TABLES ... FOR EXPORT
准备
InnoDB
表,以便从一个服务器实例复制到另一个服务器实例。
要使用此功能,
InnoDB
必须使用
innodb_file_per_table
set
创建表
,
ON
以便每个
InnoDB
表都有自己的表空间。
有关用法信息,请参见
第15.6.3.7节“将表空间复制到另一个实例”
。
MySQL Enterprise Backup产品允许您备份正在运行的MySQL数据库,同时最大限度地减少对操作的干扰,同时生成数据库的一致快照。 当MySQL Enterprise Backup复制表时,可以继续读取和写入。 此外,MySQL Enterprise Backup可以创建压缩备份文件,并备份表的子集。 结合MySQL二进制日志,您可以执行时间点恢复。 MySQL Enterprise Backup作为MySQL Enterprise订阅的一部分包含在内。
有关MySQL Enterprise Backup的更多详细信息,请参见 第30.2节“MySQL Enterprise Backup概述” 。
InnoDB
只需复制
第15.17.1节“InnoDB备份”中
“冷备份”下列出的所有相关文件,
即可移动
数据库
。
InnoDB
数据和日志文件在具有相同浮点数格式的所有平台上是二进制兼容的。
如果浮点格式不同,但是你有没有使用
FLOAT
或
DOUBLE
在您的表中的数据类型,则过程是一样:简单地拷贝相关文件。
移动或复制每个
.ibd
文件的文件时,源系统和目标系统上的数据库目录名必须相同。
存储在
InnoDB
共享表空间中
的表定义
包括数据库名称。
存储在表空间文件中的事务ID和日志序列号在数据库之间也不同。
要将
.ibd
文件和关联表从一个数据库移动到另一个数据库,请使用以下
RENAME
TABLE
语句:
RENAME TABLEdb1.tbl_name
TOdb2.tbl_name
;
如果您对文件进行了
“
干净
”
备份
.ibd
,则可以将其还原到源自它的MySQL安装,如下所示:
自复制
.ibd
文件
以来,不得删除或截断
该表,因为这样做会更改存储在表空间内的表ID。
发出此
ALTER
TABLE
语句以删除当前
.ibd
文件:
ALTER TABLE tbl_name
DISCARD TABLESPACE;
将备份
.ibd
文件
复制
到正确的数据库目录。
发出此
ALTER
TABLE
语句告诉
InnoDB
使用
.ibd
表
的新
文件:
ALTER TABLE tbl_name
IMPORT TABLESPACE;
该
ALTER
TABLE
... IMPORT TABLESPACE
功能不会对导入的数据强制执行外键约束。
在此上下文中,
“
干净
”
.ibd
文件备份是满足以下要求的备份:
.ibd
文件中
的事务没有未提交的修改
。
.ibd
文件
中没有未合并的插入缓冲区条目
。
Purge已从
.ibd
文件中
删除了所有删除标记的索引记录
。
mysqld
已将
.ibd
文件的
所有已修改页面
从缓冲池
刷新
到文件。
您可以
.ibd
使用以下方法
创建一个干净的备份
文件:
停止 mysqld 服务器中的 所有活动 并提交所有事务。
等到
SHOW
ENGINE INNODB STATUS
显示数据库中没有活动事务,并且主线程状态
InnoDB
为
Waiting for server
activity
。
然后,您可以制作该
.ibd
文件
的副本
。
制作
.ibd
文件
的干净副本的另一种方法
是使用MySQL Enterprise Backup产品:
使用MySQL Enterprise Backup备份
InnoDB
安装。
在备份上
启动第二个
mysqld
服务器,让它清理备份中的
.ibd
文件。
您可以使用 mysqldump 将表转储到一台计算机上,然后在另一台计算机上导入转储文件。 使用此方法,格式是否不同或表是否包含浮点数据无关紧要。
提高此方法性能的一种方法是 在导入数据时 关闭 自动提交 模式,假设表空间有足够的空间用于导入事务生成的大回滚段。 仅在导入整个表或表的一部分后进行提交。
如果您
MyISAM
要转换表格以
InnoDB
获得更好的可靠性和可扩展性,请在转换之前查看以下指南和提示。
MyISAM
在以前版本的MySQL中创建的
分区
表与MySQL 8.0不兼容。
这些表必须在升级之前准备好,方法是删除分区,或者将它们转换为
InnoDB
。
有关
更多信息
,
请参见
第23.6.2节“分区与存储引擎相关的限制”
。
当您从
MyISAM
表中
转换时
,请将
key_buffer_size
配置选项
的值降低
为释放结果不再需要的空闲内存。
增加
innodb_buffer_pool_size
配置选项
的值,该
选项执行为
InnoDB
表
分配高速缓存的类似角色
。
该
InnoDB
缓冲池
可以缓存表数据和索引数据,加快了查询,查找并保持查询结果在内存中进行再利用。
有关缓冲池大小配置的指导,请参见
第8.12.3.1节“MySQL如何使用内存”
。
因为
MyISAM
表不支持
事务
,所以您可能没有太多关注
autocommit
配置选项和
COMMIT
和
ROLLBACK
语句。
这些关键字对于允许多个会话同时读取和写入
InnoDB
表
非常重要
,从而在写入繁重的工作负载中提供了显着的可伸缩性优势。
当事务处于打开状态时,系统会在事务开始时保留数据的快照,如果系统在杂散事务保持运行时插入,更新和删除数百万行,则会导致大量开销。 因此,请注意避免运行时间过长的事务:
如果您正在使用
mysql
会话进行交互式实验,请
COMMIT
在完成后
始终
(完成更改)或
ROLLBACK
(撤消更改)。
关闭交互式会话,而不是让它们长时间保持打开状态,以避免事务长时间保持交易。
ROLLBACK
是一个相对昂贵的操作,因为
INSERT
,
UPDATE
和
DELETE
操作被写入
InnoDB
表之前
COMMIT
,期望大多数更改成功提交并且回滚很少。
在试验大量数据时,请避免对大量行进行更改,然后回滚这些更改。
使用一系列
INSERT
语句
加载大量数据时
,请定期
COMMIT
检查结果,以避免持续数小时的事务。
在数据仓库的典型加载操作中,如果出现问题,则截断表(使用
TRUNCATE
TABLE
)并从头开始而不是执行
ROLLBACK
。
前面的提示可以节省在过长的事务中可能浪费的内存和磁盘空间。
当事务比它们应该更短时,问题是I / O过多。
对于每个
COMMIT
,MySQL确保每个更改都安全地记录到磁盘,这涉及一些I / O.
对于
InnoDB
表
上的大多数操作
,您应该使用该设置
autocommit=0
。
从效率的角度看,这样就避免了在发出大量连续的不必要的I / O
INSERT
,
UPDATE
或
DELETE
语句。
从安全角度来看,
ROLLBACK
如果您在
mysql
命令行或应用程序中的异常处理程序中
出错
,这允许您发出
声明以恢复丢失或乱码的数据
。
autocommit=1
适用于
InnoDB
表
的时间
是在运行一系列查询以生成报告或分析统计信息时。
在这种情况下,没有与
COMMIT
或
相关的I / O代价
ROLLBACK
,并且
InnoDB
可以
自动优化只读工作负载
。
如果进行了一系列相关更改,请在最后一次完成所有更改
COMMIT
。
例如,如果将相关的信息片段插入到多个表中,请
COMMIT
在进行所有更改后
执行单个操作
。
或者,如果您运行多个连续
INSERT
语句,请
COMMIT
在加载所有数据后
执行单个语句
;
如果您正在进行数百万条
INSERT
语句,可能会通过发出
COMMIT
每万或数十万条记录来
分割
大额交易,因此交易不会变得太大。
请记住,即使
SELECT
语句
也会
打开一个事务,因此在交互式
mysql
会话中
运行某些报表或调试查询后
,可以发出
COMMIT
或关闭
mysql
会话。
您可能会
在MySQL错误日志或输出中
看到引用
“
死锁
”的
警告消息
SHOW
ENGINE INNODB
STATUS
。
尽管名称听起来可怕,但
死锁
并不是
InnoDB
表格
的严重问题
,通常不需要任何纠正措施。
当两个事务开始修改多个表,以不同的顺序访问表时,它们可以达到每个事务等待另一个事务的状态,并且两者都不能继续。
当
启用
死锁检测
(默认)时,MySQL立即检测到这种情况并取消(
回滚
)
“
较小
”
交易,让对方继续。
如果使用
innodb_deadlock_detect
配置选项
禁用死锁检测
,则
InnoDB
依赖于
innodb_lock_wait_timeout
设置在发生死锁时回滚事务。
无论哪种方式,您的应用程序都需要错误处理逻辑来重新启动由于死锁而被强制取消的事务。 当您重新发出与以前相同的SQL语句时,原始计时问题不再适用。 另一个事务已经完成,您的事务可以继续,或者另一个事务仍在进行中,您的事务将等待直到完成。
如果持续发生死锁警告,您可以查看应用程序代码以一致的方式重新排序SQL操作,或缩短事务。
您可以使用
innodb_print_all_deadlocks
启用
的
选项
进行测试,
以查看MySQL错误日志中的所有死锁警告,而不仅仅是
SHOW
ENGINE INNODB
STATUS
输出中
的最后一个警告
。
有关更多信息,请参见 第15.7.5节“InnoDB中的死锁” 。
要从
InnoDB
表中
获得最佳性能
,您可以调整与存储布局相关的许多参数。
当您将
MyISAM
是大的,经常访问的,并保持至关重要的数据表,调查和考虑
innodb_file_per_table
和
innodb_page_size
配置选项,以及
ROW_FORMAT
和
KEY_BLOCK_SIZE
条款
中的
CREATE
TABLE
说法。
在最初的实验中,最重要的设置是
innodb_file_per_table
。
启用此设置(默认设置)后,将
InnoDB
在
每个表的文件表
空间
中隐式创建
新
表
。
与
InnoDB
系统表空间相比,每个表的表空间允许在截断或删除表时由操作系统回收磁盘空间。
每个表的文件表空间还支持
DYNAMIC
和
COMPRESSED
行格式以及相关的功能,例如表压缩,长可变长度列的高效页外存储以及大索引前缀。
有关更多信息,请参阅
第15.6.3.2节“每个表的文件表空间”
。
您还可以将
InnoDB
表
存储
在共享通用表空间中,该表空间支持多个表和所有行格式。
有关更多信息,请参见
第15.6.3.3节“常规表空间”
。
您可以创建一个
InnoDB
表,它是MyISAM表的克隆,而不是
ALTER
TABLE
用于执行转换,以在切换之前并排测试旧表和新表。
创建
InnoDB
具有相同列和索引定义
的空
表。
使用
看到完整的
语句中使用。
将
子句
更改
为
。
SHOW CREATE TABLE
table_name
\GCREATE TABLE
ENGINE
ENGINE=INNODB
要将大量数据传输到
InnoDB
如上一节所示创建
的空
表中,请插入行
。
INSERT INTO
innodb_table
SELECT * FROM
myisam_table
ORDER BY
primary_key_columns
您还可以
InnoDB
在插入数据后
为
表
创建索引
。
从历史上看,创建新的二级索引对InnoDB来说是一个缓慢的操作,但现在您可以在加载数据后创建索引,而索引创建步骤的开销相对较小。
如果您
UNIQUE
对辅助密钥
有
约束,则可以通过在导入操作期间临时关闭唯一性检查来加速表导入:
SET unique_checks = 0;
... import operation ...
SET unique_checks = 1;
对于大表,这可以节省磁盘I / O,因为
InnoDB
可以使用其
更改缓冲区
将二级索引记录作为批处理写入。
确保数据不包含重复键。
unique_checks
允许但不要求存储引擎忽略重复键。
为了更好地控制插入过程,您可以插入大表:
INSERT INTO newtable SELECT * FROM oldtable 你的钥匙>something
和你的钥匙<=somethingelse
;
插入所有记录后,您可以重命名表。
在转换大表期间,增加
InnoDB
缓冲池
的大小
以减少磁盘I / O,最大为物理内存的80%。
您还可以增加
InnoDB
日志文件
的大小
。
如果您打算
InnoDB
在转换过程中
在
表中创建
数据的多个临时副本,
建议您在每个表的文件表空间中创建表,以便在删除表时可以回收磁盘空间。
当
innodb_file_per_table
配置选项启用(默认),新创建的
InnoDB
表在文件的每个表的表空间隐式创建。
无论是
MyISAM
直接
转换
表还是创建克隆
InnoDB
表,请确保在此过程中有足够的磁盘空间来容纳旧表和新表。
InnoDB
表需要比
MyISAM
表
更多的磁盘空间
。
如果
ALTER
TABLE
操作空间不足,则会启动回滚,如果磁盘受限,则可能需要数小时。
对于插入,
InnoDB
使用插入缓冲区将二级索引记录批量合并到索引中。
这节省了大量的磁盘I / O.
对于回滚,不使用此类机制,并且回滚可能比插入时间长30倍。
在失控回滚的情况下,如果数据库中没有有价值的数据,则建议终止数据库进程,而不是等待数百万个磁盘I / O操作完成。 有关完整的过程,请参见 第15.20.2节“强制InnoDB恢复” 。
该
PRIMARY KEY
子句是影响MySQL查询性能以及表和索引的空间使用的关键因素。
主键唯一标识表中的行。
表中的每一行都必须具有主键值,并且没有两行可以具有相同的主键值。
这些是主键的准则,然后是更详细的解释。
PRIMARY KEY
为每个表
声明一个
。
通常,它是
WHERE
查找单行时
在
子句中
引用的最重要的列
。
PRIMARY KEY
在原始
CREATE TABLE
语句中
声明该
子句
,而不是稍后通过
ALTER
TABLE
语句
添加它
。
仔细选择列及其数据类型。 首选数字列而不是字符或字符串。
如果没有要使用的另一个稳定,唯一,非空的数字列,请考虑使用自动增量列。
如果对主键列的值是否可能发生变化有任何疑问,自动增量列也是一个不错的选择。 更改主键列的值是一项昂贵的操作,可能涉及重新排列表中和每个二级索引中的数据。
考虑将 主键 添加 到任何尚未拥有的表中。 根据表格的最大投影尺寸使用最小的实际数字类型。 这可以使每一排稍微紧凑,这可以为大型桌子节省大量空间。 如果表具有任何 二级索引 , 则节省的空间将成倍增加 ,因为主键值在每个二级索引条目中重复。 除了减少磁盘上的数据大小之外,一个小的主键还可以让更多数据适合 缓冲池 ,从而加速各种操作并提高并发性。
如果表已经在某个较长的列(例如a)上具有主键
VARCHAR
,请考虑添加新的无符号
AUTO_INCREMENT
列并将主键切换到该列,即使查询中未引用该列也是如此。
这种设计变更可以在二级指标中节省大量空间。
您可以指定以前的主键列,
UNIQUE NOT NULL
以强制执行与
PRIMARY KEY
子句
相同的约束
,即防止所有这些列中出现重复或空值。
如果跨多个表传播相关信息,通常每个表对其主键使用相同的列。 例如,人员数据库可能有多个表,每个表都有一个员工编号的主键。 销售数据库可能有一些表具有客户编号的主键,而其他表具有订货号的主键。 因为使用主键的查找速度非常快,所以可以为这些表构建有效的连接查询。
如果你
PRIMARY KEY
完全
抛弃该
条款,MySQL会为你创建一个看不见
的
子句。
它是一个6字节的值,可能比您需要的长,因此浪费空间。
因为它是隐藏的,所以您无法在查询中引用它。
可靠性和可伸缩性功能
InnoDB
需要比同等
MyISAM
表
更多的磁盘存储
。
您可以稍微更改列和索引定义,以便在处理结果集时更好地利用空间,减少I / O和内存消耗,以及更有效地使用索引查找的更好的查询优化计划。
如果确实为主键设置了数字ID列,请使用该值与任何其他表中的相关值进行交叉引用,尤其是对于
连接
查询。
例如,不是接受国家/地区名称作为输入并执行搜索相同名称的查询,而是执行一次查找以确定国家/地区ID,然后执行其他查询(或单个连接查询)以在多个表中查找相关信息。
不是将客户或目录项编号存储为数字字符串,而是使用几个字节,将其转换为数字ID以进行存储和查询。
4字节无符号
INT
专栏可以索引超过40亿件物品(美国含义为10亿:1000万)。
有关不同整数类型的范围,请参见
第11.2.1节“整数类型(精确值) - INTEGER,INT,SMALLINT,TINYINT,MEDIUMINT,BIGINT”
。
InnoDB
提供了一种可配置的锁定机制,可以显着提高SQL语句的可伸缩性和性能,从而为具有
AUTO_INCREMENT
列的
表添加行
。
要将该
AUTO_INCREMENT
机制与
InnoDB
表
一起使用
,
AUTO_INCREMENT
必须将列定义为索引的一部分,以便可以
在表上
执行等效的索引
查找以获取最大列值。
通常,这是通过使列成为某些表索引的第一列来实现的。
SELECT
MAX(
ai_col
)
本节介绍
AUTO_INCREMENT
锁定模式
的行为,
不同
AUTO_INCREMENT
锁定模式设置的
使用含义
以及如何
InnoDB
初始化
AUTO_INCREMENT
计数器。
本节介绍
AUTO_INCREMENT
用于生成自动增量值
的
锁定模式
的行为
,以及每种锁定模式如何影响复制。
使用
innodb_autoinc_lock_mode
配置参数
在启动时配置自动增量锁定模式
。
以下术语用于描述
innodb_autoinc_lock_mode
设置:
“
INSERT
似的
”
陈述
在表中生成新的行中的所有语句,包括
INSERT
,
INSERT ...
SELECT
,
REPLACE
,
REPLACE
...
SELECT
,和
LOAD
DATA
。
包括
“
简单插入
”
,
“
批量插入
”
和
“
混合模式
”
插入。
“ 简单插入 ”
可以预先确定要插入的行数的语句(最初处理语句时)。
这包括单行和多行
INSERT
以及
REPLACE
没有嵌套子查询的语句,但不包括
INSERT
... ON DUPLICATE KEY UPDATE
。
“ 批量插入 ”
预先不知道要插入的行数(以及所需的自动增量值的数量)的语句。
这包括
INSERT
...
SELECT
,
REPLACE
...
SELECT
和
LOAD
DATA
声明,但不是简单的
INSERT
。
在处理每一行时,一次为列
InnoDB
分配新值
AUTO_INCREMENT
。
“ 混合模式插入 ”
这些是
“
简单插入
”
语句,它指定一些(但不是全部)新行的自动增量值。
下面
c1
是一个
示例,其中
是一
AUTO_INCREMENT
列表
t1
:
INSERT INTO t1(c1,c2)VALUES(1,'a'),(NULL,'b'),(5,'c'),(NULL,'d');
另一种类型的
“
混合模式插入
”
是
INSERT
... ON DUPLICATE KEY UPDATE
,在最坏的情况下实际上是
INSERT
后跟a
UPDATE
,其中
AUTO_INCREMENT
在更新阶段期间可以使用或不使用列
的分配值
。
innodb_autoinc_lock_mode
配置参数
有三种可能的设置
。
对于
“
传统
”
,
“
连续
”
或
“
交错
”
锁定模式,
设置分别为0,1或2
。
从MySQL 8.0开始,交错锁定模式(
innodb_autoinc_lock_mode=2
)是默认设置。
在MySQL 8.0之前,连续锁定模式是默认值(
innodb_autoinc_lock_mode=1
)。
MySQL 8.0中的交错锁定模式的默认设置反映了从基于语句的复制到基于行的复制的更改,作为默认复制类型。 基于语句的复制需要连续的自动增量锁定模式,以确保为给定的SQL语句序列以可预测和可重复的顺序分配自动增量值,而基于行的复制对SQL语句的执行顺序不敏感。
innodb_autoinc_lock_mode = 0
(
“
传统
”
锁定模式)
传统的锁定模式提供了与
innodb_autoinc_lock_mode
MySQL 5.1中引入配置参数
之前相同的行为
。
传统的锁定模式选项用于向后兼容,性能测试以及解决“混合模式插入”问题,因为语义可能存在差异。
在此锁定模式下,所有
“
INSERT-like
”
语句都会获得一个特殊的表级
AUTO-INC
锁,以便插入带有
AUTO_INCREMENT
列的表中。
此锁通常保持在语句的末尾(而不是事务的结尾),以确保为给定的
INSERT
语句
序列以可预测和可重复的顺序分配自动增量值
,并确保自动增量值由任何给定的声明分配是连续的。
对于基于语句的复制,这意味着在从属服务器上复制SQL语句时,自动增量列使用的值与主服务器上的值相同。
执行多个
INSERT
语句
的结果
是确定性的,并且从站再现与主站上相同的数据。
如果多个
INSERT
语句
生成的自动递增值
是交错的,则两个并发
INSERT
语句
的结果
将是不确定的,并且无法使用基于语句的复制可靠地传播到从属服务器。
为清楚起见,请考虑使用此表的示例:
CREATE TABLE t1( c1 INT(11)NOT NULL AUTO_INCREMENT, c2 VARCHAR(10)DEFAULT NULL, 主要关键(c1) )ENGINE = InnoDB;
假设有两个事务正在运行,每个事务都将行插入带有
AUTO_INCREMENT
列
的表中
。
一个事务使用
INSERT
...
SELECT
插入1000行
的
语句,
另一个事务使用
插入一行的简单
INSERT
语句:
Tx1:INSERT INTO t1(c2)从另一个表中选择1000行... Tx2:INSERT INTO t1(c2)VALUES('xxx');
InnoDB
事先无法判断从
Tx1
SELECT
中的
INSERT
语句中
检索了多少行
,并且
随着
语句的进行,它会一次分配一个自动增量值。
使用保持在语句末尾的表级锁定,一次只能
执行
一个
INSERT
引用表的语句
t1
,并且不会交错生成不同语句的自动增量数。
由Tx1
INSERT
...
SELECT
语句
生成的自动递增值
是连续的,并且由(单个)自动递增值使用
INSERT
Tx2中的语句要小于或大于用于Tx1的语句,具体取决于首先执行的语句。
只要SQL语句在从二进制日志重放时(在使用基于语句的复制时或在恢复方案中)以相同的顺序执行,结果与首次运行Tx1和Tx2时的结果相同。
因此,表级锁定一直持续到语句结束时,
INSERT
使用自动增量安全
的语句可以
安全地用于基于语句的复制。
但是,当多个事务同时执行insert语句时,这些表级锁限制了并发性和可伸缩性。
在前面的示例中,如果没有表级锁定,则用于
INSERT
Tx2
中的自动增量列的值
取决于语句执行的时间。
如果
INSERT
Tx2在
INSERT
Tx1运行时执行(而不是在启动之前或完成之后),则由两个
INSERT
语句
分配的特定自动增量值
是不确定的,并且可能因运行而异。
在
连续
锁定模式下,
InnoDB
可以避免将表级
AUTO-INC
锁定用于
预先知道行数的
“
简单插入
”
语句,并且仍然保留基于语句的复制的确定性执行和安全性。
如果您不使用二进制日志作为恢复或复制的一部分重放SQL语句,则
交错
锁定模式可用于消除表级
AUTO-INC
锁的
所有使用,从而
实现更高的并发性和性能,但代价是允许自动存在空白 - 由语句分配的增量编号,可能具有由并发执行的语句交错分配的编号。
innodb_autoinc_lock_mode = 1
(
“
连续
”
锁定模式)
在此模式下,
“
批量插入
”
使用特殊的
AUTO-INC
表级锁定并保持它直到语句结束。
这适用于所有
INSERT
...
SELECT
,
REPLACE
...
SELECT
和
LOAD
DATA
语句。
只有一个持有
AUTO-INC
锁的
语句
可以一次执行。
如果批量插入操作的源表与目标表不同,则
AUTO-INC
在从源表中选择的第一行上执行共享锁之后,将对目标表执行锁定。
如果批量插入操作的源和目标是同一个表,则
AUTO-INC
在对所有选定的行执行共享锁定后执行锁定。
“
简单插入
”
(预先知道要插入的行数)
AUTO-INC
通过在互斥锁(轻量级锁定)的控制下获得所需数量的自动增量值来
避免表级
锁定在分配过程的持续时间内保持,
不
直到语句完成。
AUTO-INC
除非
AUTO-INC
另一个事务持有
锁,否则
不使用表级
锁
。
如果另一个事务持有
AUTO-INC
锁,则
“
简单插入
”
等待
AUTO-INC
锁定,就像它是
“
批量插入
“
。
此锁定模式确保在存在
INSERT
未提前知道行数
的
语句(以及在语句进行时指定自动增量编号)的情况下,由任何
“
INSERT
-like
”
语句
指定的所有自动增量值
都是连续,并且操作对于基于语句的复制是安全的。
简而言之,这种锁定模式显着提高了可伸缩性,同时可以安全地使用基于语句的复制。 此外,与 “ 传统 ” 锁定模式一样,由任何给定语句分配的自动递增数字是 连续的 。 有 没有变化 在语义比较 “ 传统 ” 对于使用自动递增,有一个重要的例外,任何声明模式。
“
混合模式插入
”
的例外情况是,
用户为
AUTO_INCREMENT
多行
“
简单插入
”中的
某些行(但不是所有行)
提供
列的
显式值
。
对于此类插入,请
InnoDB
分配比要插入的行数更多的自动增量值。
但是,自动分配的所有值都是连续生成(因此高于)最近执行的先前语句生成的自动增量值。
“
超额
”
号码丢失了。
innodb_autoinc_lock_mode = 2
(
“
交错
”
锁定模式)
在此锁定模式下,没有
“
INSERT
-like
”
语句使用表级
AUTO-INC
锁,并且多个语句可以同时执行。
这是最快且最具扩展性的锁定模式,但
在从二进制日志重放SQL语句时使用基于语句的复制或恢复方案时
,这是
不安全的
。
在这种锁定模式下,自动增量值保证是唯一的,并且在所有同时执行的
“
INSERT
类似
”
语句中
单调递增
。
但是,因为多个语句可以同时生成数字(即,数字的分配
在语句之间
交错
),所以为任何给定语句插入的行生成的值可能不是连续的。
如果执行的唯一语句是 “ 简单插入 ” ,其中要插入的行数是提前知道的,则除了 “ 混合模式插入 ” 之外,单个语句生成的数字没有间隙 。 但是,当 执行 “ 批量插入 ” 时 ,任何给定语句分配的自动增量值可能存在间隙。
使用复制自动增量
如果使用基于语句的复制,请设置
innodb_autoinc_lock_mode
为0或1,并在主服务器及其从服务器上使用相同的值。
如果使用
innodb_autoinc_lock_mode
= 2(
“
交错
”
)或主站和从站不使用相同锁定模式的配置,
则不确保从站上的自动增量值
与主站上的相同。
如果使用基于行或混合格式的复制,则所有自动增量锁定模式都是安全的,因为基于行的复制对SQL语句的执行顺序不敏感(并且混合格式使用基于行的方式)复制任何对基于语句的复制不安全的语句。
“ 丢失 ” 自动递增值和序列间隙
在所有锁定模式(0,1和2)中,如果生成自动增量值的事务回滚,则这些自动增量值将
“
丢失
”
。
一旦为自动增量列生成了值,就无法回滚它,无论
“
INSERT
-like
”
语句是否完成,以及是否回滚包含的事务。
这些丢失的值不会被重用。
因此,存储在
AUTO_INCREMENT
表
的
列
中的值可能存在间隙
。
为
AUTO_INCREMENT
列
指定NULL或0
在所有的锁模式(0,1,2),如果用户指定NULL或0用于
AUTO_INCREMENT
在列
INSERT
,
InnoDB
将行仿佛没有指定值,并且生成用于它的新值。
为
AUTO_INCREMENT
列
指定负值
在所有锁定模式(0,1和2)中,如果为
AUTO_INCREMENT
列
指定负值,则不会定义自动增量机制的行为
。
如果该
AUTO_INCREMENT
值大于指定整数类型的最大整数
在所有锁定模式(0,1和2)中,如果值大于可以存储在指定整数类型中的最大整数,则不会定义自动增量机制的行为。
“ 批量插入 ”的 自动增量值的差距
与
innodb_autoinc_lock_mode
设定为0(
“
传统
”
)或1(
“
连续
”
),通过任何给定语句生成的自动递增的值是连续的,没有间隙,这是因为表级
AUTO-INC
锁一直保持到该语句的末尾,只有一个这样的语句可以一次执行。
与
innodb_autoinc_lock_mode
设置为2(
“
交织
”
),有可能是在所产生的自动递增值间隙
“
批量插入
, ”
但只有当有同时执行的
“
INSERT
样
”
的语句。
对于锁定模式1或2,在连续语句之间可能出现间隙,因为对于批量插入,可能不知道每个语句所需的确切数量的自动增量值,并且可能过高估计。
由 “ 混合模式插入 ” 指定的自动递增值
考虑
“
混合模式插入
”
,其中
“
简单插入
”
指定某些(但不是全部)结果行的自动增量值。
这种语句在锁定模式0,1和2中表现不同。例如,假设
c1
是一
AUTO_INCREMENT
列表
t1
,并且最近自动生成的序列号是100。
mysql>CREATE TABLE t1 (
- >c1 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
- >c2 CHAR(1)
- >) ENGINE = INNODB;
现在,考虑以下 “ 混合模式插入 ” 语句:
MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
随着
innodb_autoinc_lock_mode
设置为0(
“
传统
”
),这四个新的行是:
MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
+ ----- + ------ +
| c1 | c2 |
+ ----- + ------ +
| 1 | a |
| 101 | b |
| 5 | c |
| 102 | d |
+ ----- + ------ +
下一个可用的自动增量值为103,因为自动增量值一次分配一个,而不是在语句执行开始时一次分配。
无论是否同时执行
“
INSERT
-like
”
语句(任何类型),
此结果都是正确的
。
随着
innodb_autoinc_lock_mode
设置为1(
“
连续
”
),这四个新行也:
MySQL的> SELECT c1, c2 FROM t1 ORDER BY c2;
+ ----- + ------ +
| c1 | c2 |
+ ----- + ------ +
| 1 | a |
| 101 | b |
| 5 | c |
| 102 | d |
+ ----- + ------ +
但是,在这种情况下,下一个可用的自动增量值是105,而不是103,因为在处理语句时分配了四个自动增量值,但只使用了两个。
无论是否同时执行
“
INSERT
-like
”
语句(任何类型),
此结果都是正确的
。
与
innodb_autoinc_lock_mode
设定为模式2(
“
交织
”
),四个新的行是:
MySQL的>SELECT c1, c2 FROM t1 ORDER BY c2;
+ ----- + ------ + | c1 | c2 | + ----- + ------ + | 1 | a | |x
| b | | 5 | c | |y
| d | + ----- + ------ +
的值
x
和
y
是独一无二的,比任何先前产生的行大。
然而,具体的数值
x
,并
y
依赖于并行执行语句生成自动递增值的数量。
最后,考虑以下语句,在最近生成的序列号为100时发出:
MySQL的> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (101,'c'), (NULL,'d');
对于任何
innodb_autoinc_lock_mode
设置,此语句将生成重复键错误23000(
Can't write; duplicate key in
table
),因为为行分配了101并且行的
(NULL, 'b')
插入
(101, 'c')
失败。
AUTO_INCREMENT
在一系列
INSERT
语句
的中间
修改
列值
在MySQL 5.7及更早版本中,修改
语句
AUTO_INCREMENT
序列中间
的
列值
INSERT
可能会导致
“
重复条目
”
错误。
例如,如果执行的
UPDATE
操作将
AUTO_INCREMENT
列值
更改为
大于当前最大自动增量值的值,则
INSERT
未指定未使用的自动增量值的
后续
操作可能会遇到
“
重复条目
”
错误。
在MySQL 8.0及更高版本中,如果您修改了
AUTO_INCREMENT
如果列值大于当前最大自动增量值,则新值将保持不变,后续
INSERT
操作将从新的较大值开始分配自动增量值。
以下示例演示了此行为。
mysql>CREATE TABLE t1 (
- >c1 INT NOT NULL AUTO_INCREMENT,
- >PRIMARY KEY (c1)
- >) ENGINE = InnoDB;
MySQL的>INSERT INTO t1 VALUES(0), (0), (3);
MySQL的>SELECT c1 FROM t1;
+ ---- + | c1 | + ---- + | 1 | | 2 | | 3 | + ---- + MySQL的>UPDATE t1 SET c1 = 4 WHERE c1 = 1;
MySQL的>SELECT c1 FROM t1;
+ ---- + | c1 | + ---- + | 2 | | 3 | | 4 | + ---- + MySQL的>INSERT INTO t1 VALUES(0);
MySQL的>SELECT c1 FROM t1;
+ ---- + | c1 | + ---- + | 2 | | 3 | | 4 | | 5 | + ---- +
本节介绍如何
InnoDB
初始化
AUTO_INCREMENT
计数器。
如果
AUTO_INCREMENT
为
InnoDB
表
指定
列
,则内存中表对象包含一个称为自动增量计数器的特殊计数器,该计数器在为列分配新值时使用。
在MySQL 5.7及更早版本中,自动增量计数器仅存储在主存储器中,而不存储在磁盘上。
要在服务器重新启动后初始化自动增量计数器,
InnoDB
将在第一次插入到包含
AUTO_INCREMENT
列
的表中执行以下语句的等效语句
。
SELECT MAX(ai_col)FROM table_name
FOR UPDATE;
在MySQL 8.0中,此行为已更改。 每次更改时,当前最大自动增量计数器值将写入重做日志,并保存到每个检查点上的引擎专用系统表中。 这些更改使当前最大自动增量计数器值在服务器重新启动时保持不变。
在正常关闭后重新启动服务器上,
InnoDB
使用存储在数据字典系统表中的当前最大自动增量值初始化内存中自动递增计数器。
在崩溃恢复期间在服务器上重新启动时,
InnoDB
使用存储在数据字典系统表中的当前最大自动增量值初始化内存中自动增量计数器,并扫描重做日志以查找自上一个检查点以来写入的自动增量计数器值。
如果重做日志值大于内存中计数器值,则应用重做日志值。
但是,在服务器崩溃的情况下,无法保证重用先前分配的自动增量值。
每次由于
INSERT
或
更改当前最大自动增量值
UPDATE
操作时,新值将写入重做日志,但如果在重做日志刷新到磁盘之前发生崩溃,则在重新启动服务器后初始化自动增量计数器时,可以重用先前分配的值。
在MySQL 8.0及更高版本中
InnoDB
使用等效
语句来初始化自动增量计数器
的唯一情况
是在
导入
没有
元数据文件
的表空间
时
。
否则,从
元数据文件中
读取当前最大自动增量计数器值
。
SELECT MAX(ai_col) FROM
table_name
FOR UPDATE.cfg
.cfg
在MySQL 5.7及更早版本中,服务器重新启动会取消
AUTO_INCREMENT = N
table选项
的效果,该
选项可以在
CREATE TABLE
or
ALTER TABLE
语句中用于设置初始计数器值或分别更改现有计数器值。
在MySQL 8.0中,服务器重新启动不会取消
AUTO_INCREMENT = N
表选项
的效果
。
如果将自动递增计数器初始化为特定值,或者将自动递增计数器值更改为更大的值,则新值将在服务器重新启动时保持不变。
ALTER
TABLE ...
AUTO_INCREMENT = N
只能将自动增量计数器值更改为大于当前最大值的值。
在MySQL 5.7及更早版本中,服务器在
ROLLBACK
操作后
立即重新启动
可能会导致重用先前分配给回滚事务的自动增量值,从而有效地回滚当前的最大自动增量值。
在MySQL 8.0中,当前的最大自动增量值是持久的,从而阻止了以前分配的值的重用。
如果
SHOW TABLE STATUS
语句在初始化自动增量计数器之前检查表,则
InnoDB
打开表并使用存储在数据字典系统表中的当前最大自动增量值初始化计数器值。
该值存储在内存中以供以后插入或更新使用。
计数器值的初始化使用表上的常规异或锁定读取,该读取持续到事务结束。
InnoDB
在为具有用户指定的自动增量值大于0的新创建的表初始化自动增量计数器时,遵循相同的过程。
初始化自动递增计数器后,如果在插入行时未显式指定自动递增值,则
InnoDB
隐式递增计数器并将新值分配给列。
如果插入显式指定自动增量列值的行,并且该值大于当前最大计数器值,则计数器将设置为指定值。
InnoDB
只要服务器运行,就使用内存中的自动增量计数器。
停止并重新启动服务器时,
InnoDB
重新初始化自动增量计数器,如前所述。
的
auto_increment_offset
配置选项确定为起点
AUTO_INCREMENT
列值。
默认设置为1。
的
auto_increment_increment
配置选项控制连续列的值之间的间隔。
默认设置为1。
InnoDB
本节中的以下主题描述
了
存储引擎
如何
处理外键约束:
有关外键使用信息和示例,请参见 第13.1.20.6节“使用FOREIGN KEY约束” 。
InnoDB
表的
外键定义符合
以下条件:
InnoDB
允许外键引用任何索引列或列组。
但是,在引用的表中,必须有一个索引,其中引用的列是
同一顺序
中的
第一
列。
InnoDB
还会考虑添加到索引的
隐藏列
(请参见
第15.6.2.1节“聚簇和二级索引”
)。
InnoDB
当前不支持具有用户定义分区的表的外键。
这意味着没有用户分区的
InnoDB
表可能包含外键引用的外键引用或列。
InnoDB
允许外键约束引用非唯一键。
这是
InnoDB
标准SQL
的
扩展。
InnoDB
表的
外键的引用操作
受以下条件限制:
虽然
SET DEFAULT
MySQL服务器允许,但它被拒绝为无效
InnoDB
。
CREATE
TABLE
并
ALTER
TABLE
利用这一条款语句不得用于InnoDB表。
如果父表中有多个行具有相同的引用键值,则
InnoDB
在外键检查中执行操作,就好像其他具有相同键值的父行不存在一样。
例如,如果已定义
RESTRICT
类型约束,并且存在具有多个父行的子行,
InnoDB
则不允许删除任何这些父行。
InnoDB
基于对应于外键约束的索引中的记录,通过深度优先算法执行级联操作。
如果
ON UPDATE CASCADE
或者
ON
UPDATE SET NULL
recurses更新
它在级联期间先前已
更新的
同一个表
,它的作用就像
RESTRICT
。
这意味着您不能使用自引用
ON UPDATE CASCADE
或
ON UPDATE SET NULL
操作。
这是为了防止级联更新导致的无限循环。
自引用的
ON DELETE SET NULL
,在另一方面,是可能的,因为是自引用
ON DELETE CASCADE
。
级联操作可能不会嵌套超过15级。
与MySQL一样,在一个SQL语句中,
逐行
插入,删除或更新许多行,
InnoDB
检查
UNIQUE
和
FOREIGN
KEY
约束。
执行外键检查时,
InnoDB
在必须查看的子记录或父记录上设置共享行级锁。
InnoDB
立即检查外键约束;
检查不会延迟到事务提交。
根据SQL标准,默认行为应该是延迟检查。
也就是说,只有在处理
完整个SQL语句
后才会检查约束
。
直到
InnoDB
实现延迟约束检查,有些事情是不可能的,例如删除使用外键引用自身的记录。
在存储生成列外键约束不能使用
CASCADE
,
SET NULL
或
SET DEFAULT
作为
ON
UPDATE
参照动作,也不能使用
SET NULL
或
SET
DEFAULT
作为
ON DELETE
参照动作。
在存储生成列的基本列外键约束不能使用
CASCADE
,
SET NULL
或
SET
DEFAULT
作为
ON UPDATE
或
ON DELETE
引用操作。
外键约束不能引用 虚拟生成的列 。
在MySQL 8.0之前,外键约束不能引用在虚拟生成列上定义的辅助索引。
InnoDB
表中的
限制
在本节的以下主题中描述:
在使用NFS之前
InnoDB
,请查看
使用NFS与MySQL中
概述的潜在问题
。
一个表最多可包含1017列。 虚拟生成列包含在此限制中。
一个表最多可包含64个 二级索引 。
对于
InnoDB
使用
DYNAMIC
或
COMPRESSED
行格式的
表,
索引键前缀长度限制为3072字节
。
对于
InnoDB
使用
REDUNDANT
或
COMPACT
行格式的
表,
索引键前缀长度限制为767字节
。
例如,您可能会
在一个
或一
列
上使用超过191个字符
的
列前缀
索引
达到此限制
,假定
为每个字符设置
一个
字符集且最多为4个字节。
TEXT
VARCHAR
utf8mb4
尝试使用超出限制的索引键前缀长度会返回错误。
适用于索引键前缀的限制也适用于全列索引键。
如果
通过
在创建MySQL实例时
指定
选项
将
InnoDB
页面大小减小
到8KB或4KB
innodb_page_size
,则索引键的最大长度将按比例降低,基于16KB页面大小的3072字节限制。
也就是说,当页面大小为8KB时,最大索引密钥长度为1536字节,当页面大小为4KB时,最大索引密钥长度为768字节。
多列索引最多允许16列。 超过限制会返回错误。
ERROR 1070(42000):指定的关键部件太多; 最多允许16件
最大行长度,除了可变长度列(
VARBINARY
,
VARCHAR
,
BLOB
和
TEXT
),是比对于4KB,8KB,16KB,32KB和页大小的页的一半稍少。
例如,默认
innodb_page_size
值为16KB
的最大行长度
约为8000字节。
对于
InnoDB
64KB
的
页面大小,最大行长度约为16000字节。
LONGBLOB
和
LONGTEXT
列必须小于4GB,并且总行长度(包括
列
BLOB
和
TEXT
列)必须小于4GB。
如果一行长度小于半页,则所有行都存储在页面内。 如果它超过半页,则选择可变长度列用于外部页外存储,直到该行适合半页,如 第15.11.2节“文件空间管理”中所述 。
虽然
InnoDB
内部支持的行大小超过65,535字节,但MySQL本身对所有列的总大小强加了行大小限制为65,535:
mysql>CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
- >c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
- >f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
ERROR 1118(42000):行大小太大。最大行大小 使用的表类型,不计算BLOB,是65535.你必须改变一些 列到TEXT或BLOB
请参见 第C.10.4节“表列数和行大小的限制” 。
在某些较旧的操作系统上,文件必须小于2GB。
这不是
InnoDB
自身
的限制
,但如果您需要大型表空间,请使用几个较小的数据文件而不是一个大型数据文件进行配置。
InnoDB
日志文件
的总大小
最大可达512GB。
最小表空间大小略大于10MB。
最大表空间大小取决于
InnoDB
页面大小。
最大表空间大小也是表的最大大小。
表空间文件的路径(包括文件名)不能超过
MAX_PATH
Windows上
的
限制。
在Windows 10之前,
MAX_PATH
限制为260个字符。
从Windows 10版本1607开始,
MAX_PATH
从常见的Win32文件和目录函数中删除了限制,但您必须启用新行为。
默认页面大小
InnoDB
为16KB。
您可以通过
innodb_page_size
在创建MySQL实例时
配置
选项
来增加或减少页面大小
。
支持32KB和64KB页面大小,但
ROW_FORMAT=COMPRESSED
不支持大于16KB的页面大小。
对于32KB和64KB页面大小,最大记录大小为16KB。
对于
innodb_page_size=32KB
,范围大小为2MB。
对于
innodb_page_size=64KB
,范围大小是4MB。
使用特定
InnoDB
页面大小的
MySQL实例
无法使用来自使用不同页面大小的实例的数据文件或日志文件。
ANALYZE
TABLE
通过
对每个索引树
执行
随机潜水
并相应地更新索引基数估计
来确定索引基数(显示在
输出
Cardinality
列中
SHOW
INDEX
)
。
因为这些只是估计,所以重复运行
会产生不同的数字。
这使得
表格
快速
但不是100%准确,因为它不会考虑所有行。
ANALYZE
TABLE
ANALYZE TABLE
InnoDB
通过打开
配置选项,
您可以
更精确,更稳定地
收集
统计信息
,如
第15.8.10.1节“配置持久优化器统计信息参数”中所述
。
启用该设置
后,在对索引列数据进行重大更改后
运行非常重要
,因为不会定期重新计算统计信息(例如在服务器重新启动后)。
ANALYZE
TABLE
innodb_stats_persistent
ANALYZE TABLE
如果启用了持久性统计设置,则可以通过修改
innodb_stats_persistent_sample_pages
系统变量
来更改随机潜水次数
。
如果禁用持久统计信息设置,请
innodb_stats_transient_sample_pages
改为
修改
系统变量。
MySQL在连接优化中使用索引基数估计。
如果未以正确的方式优化连接,请尝试使用
ANALYZE
TABLE
。
在少数几个
ANALYZE
TABLE
不能为您的特定表生成足够好的值的
情况下
,您可以使用
FORCE INDEX
查询来强制使用特定索引,或者设置
max_seeks_for_key
系统变量以确保MySQL更喜欢对表扫描进行索引查找。
请参见
第B.4.5节“与优化程序相关的问题”
。
如果语句或事务在表上运行,并且
ANALYZE
TABLE
在同
一个表
上运行,然后执行第二个
ANALYZE
TABLE
操作,则第二个
ANALYZE
TABLE
操作将被阻止,直到语句或事务完成为止。
出现此问题的原因
是
ANALYZE
TABLE
当
ANALYZE
TABLE
完成运行
时将当前加载的表定义标记为已过时
。
新的陈述或交易(包括第二次
ANALYZE
TABLE
必须将新表定义加载到表缓存中,直到当前运行的语句或事务完成并清除旧表定义时才会发生这种情况。
不支持加载多个并发表定义。
SHOW
TABLE STATUS
InnoDB
除了表保留的物理大小之外,
没有给出
表的
准确统计信息
。
行计数只是SQL优化中使用的粗略估计。
InnoDB
不保留表中的内部行数,因为并发事务可能同时
“
看到
”
不同数量的行。
因此,
SELECT COUNT(*)
语句只计算当前事务可见的行。
有关信息如何
InnoDB
处理
SELECT COUNT(*)
报表,请参阅
COUNT()
说明在
第12.20.1,“集合(GROUP BY)功能说明”
。
在Windows上,
InnoDB
始终以小写形式在内部存储数据库和表名。
要以二进制格式将数据库从Unix移动到Windows或从Windows移动到Unix,请使用小写名称创建所有数据库和表。
一
AUTO_INCREMENT
列
ai_col
必须被定义为一个指数,使得它能够进行一个索引的等效的部分
上的表查找以获得最大列值。
通常,这是通过使列成为某些表索引的第一列来实现的。
SELECT
MAX(
ai_col
)
InnoDB
AUTO_INCREMENT
在初始化
AUTO_INCREMENT
表上的
先前指定的
列时,在
与
列
关联的索引的末尾设置独占锁
。
使用
innodb_autoinc_lock_mode=0
,
InnoDB
使用特殊的
AUTO-INC
表锁定模式,其中获取锁定并在访问自动增量计数器时保持到当前SQL语句的末尾。
在保持
AUTO-INC
表锁定
时,其他客户端无法插入表中
。
对于发生相同的行为
“
批量插入
”
与
innodb_autoinc_lock_mode=1
。
表级
AUTO-INC
锁不用于
innodb_autoinc_lock_mode=2
。
有关更多信息,请参见
第15.6.1.4节“InnoDB中的AUTO_INCREMENT处理”
。
当
AUTO_INCREMENT
整数列用完值时,后续
INSERT
操作将返回重复键错误。
这是一般的MySQL行为。
DELETE FROM
不会重新生成表,而是逐个删除所有行。
tbl_name
级联外键操作不会激活触发器。
不能创建与内部的名称匹配的列名的表
InnoDB
列(其中包括
DB_ROW_ID
,
DB_TRX_ID
,
DB_ROLL_PTR
,和
DB_MIX_ID
)。
此限制适用于在任何字母大小写中使用名称。
MySQL的> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
错误1166(42000):错误的列名'db_row_id'
LOCK
TABLES
如果
innodb_table_locks=1
(默认值),
则在每个表上获取两个锁
。
除了MySQL层上的表锁之外,它还获取
InnoDB
表锁。
4.1.2之前的MySQL版本没有获取
InnoDB
表锁;
可以通过设置选择旧行为
innodb_table_locks=0
。
如果未
InnoDB
获取表锁,
LOCK TABLES
即使某些表的记录被其他事务锁定
,
也会完成。
在MySQL 8.0中,
innodb_table_locks=0
对于显式锁定的表没有任何影响
LOCK TABLES ...
WRITE
。
它对通过
LOCK TABLES ...
WRITE
隐式(例如,通过触发器)或通过隐藏(例如,通过触发器)
锁定读取或写入的表有效
LOCK
TABLES ... READ
。
InnoDB
事务提交或中止时,将释放事务持有的
所有
锁。
因此,它并没有多大意义,调用
LOCK TABLES
上
InnoDB
表中
autocommit=1
模式,因为所获得的
InnoDB
表锁将被立即释放。
您无法在事务中锁定其他表,因为
LOCK
TABLES
执行隐式
COMMIT
和
UNLOCK
TABLES
。
有关与并发读写事务关联的限制,请参见 第15.6.6节“撤消日志” 。
本节介绍与
InnoDB
索引
相关的主题
。
每个
InnoDB
表都有一个称为
聚簇索引
的特殊索引,
其中存储了行的数据。
通常,聚簇索引与
主键
同义
。
要从查询,插入和其他数据库操作中获得最佳性能,您必须了解如何
InnoDB
使用聚簇索引来优化每个表的最常见查找和DML操作。
在
PRIMARY KEY
表上
定义a
时,
InnoDB
将其用作聚簇索引。
为您创建的每个表定义主键。
如果没有逻辑唯一且非空列或列集,请添加一个新的
自动增量
列,其值将自动填充。
如果没有
PRIMARY KEY
为表
定义一个
,MySQL将找到
UNIQUE
所有键列
所在的第一个
索引,
NOT NULL
并将
InnoDB
其用作聚簇索引。
如果表没有
PRIMARY KEY
或
没有
合适的
UNIQUE
索引,则在
InnoDB
内部生成一个隐藏的聚簇索引
GEN_CLUST_INDEX
,该
索引
在包含行ID值的合成列上
命名
。
行按照
InnoDB
分配给此类表中的行
的ID排序
。
行ID是一个6字节的字段,随着新行的插入而单调增加。
因此,由行ID排序的行在物理上处于插入顺序。
通过聚簇索引访问行很快,因为索引搜索直接指向包含所有行数据的页面。 如果表很大,与使用与索引记录不同的页面存储行数据的存储组织相比,聚簇索引体系结构通常会保存磁盘I / O操作。
除聚簇索引之外的所有索引都称为
辅助索引
。
在
InnoDB
,辅助索引中的每个记录都包含该行的主键列,以及为二级索引指定的列。
InnoDB
使用此主键值来搜索聚簇索引中的行。
如果主键很长,则二级索引使用更多空间,因此使用短主键是有利的。
有关利用
InnoDB
聚簇索引和二级索引的
准则
,请参见
第8.3节“优化和索引”
。
除空间索引外,
InnoDB
索引是
B树
数据结构。
空间索引使用
R树
,
R树
是用于索引多维数据的专用数据结构。
索引记录存储在其B树或R树数据结构的叶页中。
索引页的默认大小为16KB。
将新记录插入
InnoDB
聚簇索引时
,
InnoDB
尝试将页面的1/16保留为可用,以便将来插入和更新索引记录。
如果索引记录按顺序(升序或降序)插入,则生成的索引页大约为15/16。
如果以随机顺序插入记录,则页面从1/2到15/16满。
InnoDB
在创建或重建B树索引时执行批量加载。
这种索引创建方法称为排序索引构建。
该
innodb_fill_factor
配置选项定义的空间作为排序指标构建过程中填充,为今后指数增长预留的剩余空间每个B树页的百分比。
空间索引不支持排序索引构建。
有关更多信息,请参见
第15.6.2.3节“排序索引构建”
。
一个
innodb_fill_factor
100设置叶免费为未来指数增长的聚簇索引页的空间的1/16。
如果
InnoDB
索引页
的填充因子
低于
MERGE_THRESHOLD
默认值(如果未指定则为50%),则
InnoDB
尝试收缩索引树以释放页面。
该
MERGE_THRESHOLD
设置适用于B树和R树索引。
有关更多信息,请参见
第15.8.11节“配置索引页的合并阈值”
。
您可以
通过
在初始化MySQL实例之前
设置
配置选项
来定义
MySQL实例中
所有
表空间
的
页面大小
。
定义实例的页面大小后,如果不重新初始化实例,则无法更改它。
支持的大小为64KB,32KB,16KB(默认),8KB和4KB。
InnoDB
innodb_page_size
使用特定
InnoDB
页面大小的
MySQL实例
无法使用来自使用不同页面大小的实例的数据文件或日志文件。
InnoDB
在创建或重建索引时,执行批量加载而不是一次插入一个索引记录。
这种索引创建方法也称为排序索引构建。
空间索引不支持排序索引构建。
索引构建有三个阶段。 在第一阶段, 扫描 聚簇索引 ,生成索引条目并将其添加到排序缓冲区。 当 排序缓冲区 变满时,条目将被排序并写入临时中间文件。 此过程也称为 “ 运行 ” 。 在第二阶段,将一个或多个运行写入临时中间文件,对文件中的所有条目执行合并排序。 在第三个也是最后一个阶段,已排序的条目将插入到 B树中 。
在引入排序索引构建之前,使用插入API一次将索引条目插入到B树中一条记录。 此方法涉及打开B树 游标 以查找插入位置,然后使用 乐观 插入 将条目插入B树页面 。 如果由于页面已满而导致插入失败, 则将执行 悲观 插入,这涉及打开B树游标并根据需要拆分和合并B树节点以查找条目的空间。 这种 “ 自上而下 ” 的弊端 构建索引的方法是搜索插入位置的成本以及B树节点的常量拆分和合并。
排序索引构建使用 “ 自下而上 ” 构建索引的方法。 使用这种方法,对最右侧叶页的引用保存在B树的所有级别。 分配必要B树深度的最右侧叶页,并根据其排序顺序插入条目。 一旦叶子页面已满,节点指针将附加到父页面,并为下一个插入分配一个兄弟叶页面。 此过程将继续,直到插入所有条目,这可能导致插入到根级别。 分配兄弟页面时,将释放对先前固定的叶子页面的引用,并且新分配的叶子页面将成为最右侧的叶子页面和新的默认插入位置。
要为将来的索引增长留出空间,可以使用
innodb_fill_factor
配置选项保留B树页面空间的百分比。
例如,
innodb_fill_factor
在排序索引构建期间
,设置
为80可保留B树页面中20%的空间。
此设置适用于B树叶和非叶页。
它不适用于用于
TEXT
或
BLOB
输入的
外部页面
。
保留的空间量可能与配置的不完全相同,因为该
innodb_fill_factor
值被解释为提示而不是硬限制。
全文索引 支持排序索引构建 。 以前,SQL用于将条目插入到全文索引中。
对于 压缩表 ,先前的索引创建方法将条目附加到压缩和未压缩页面。 当修改日志(表示压缩页面上的可用空间)变满时,压缩页面将被重新压缩。 如果由于空间不足而导致压缩失败,则页面将被拆分。 对于已排序的索引构建,条目仅附加到未压缩的页面。 当未压缩的页面变满时,它将被压缩。 自适应填充用于确保在大多数情况下压缩成功,但如果压缩失败,则会拆分页面并再次尝试压缩。 此过程将继续,直到压缩成功。 有关压缩B-Tree页面的更多信息,请参阅 第15.9.1.5节“压缩如何用于InnoDB表” 。
在排序的索引构建期间禁用 重做日志记录 。 相反,有一个 检查点 可确保索引构建能够承受崩溃或故障。 检查点强制将所有脏页写入磁盘。 在排序索引构建期间, 定期发信号通知 页面清理器 线程以刷新 脏页面 以确保可以快速处理检查点操作。 通常,当清洁页面的数量低于设定阈值时,页面清理器线程会刷新脏页面。 对于排序索引构建,会立即刷新脏页以减少检查点开销并并行化I / O和CPU活动。
排序索引构建可能导致 优化程序 统计信息与以前的索引创建方法生成的统计信息不同。 统计数据的差异(预计不会影响工作负载性能)是由于用于填充索引的算法不同。
FULLTEXT
索引是在基于文本的列(
CHAR
,
VARCHAR
或
TEXT
列)
上创建的
,
以帮助加快对这些列中包含的数据的查询和DML操作,省略任何定义为停用词的单词。
甲
FULLTEXT
指数被定义为一个的一部分
CREATE
TABLE
说明或使用添加到现有的表
ALTER
TABLE
或
CREATE
INDEX
。
使用
MATCH()
... AGAINST
语法
执行全文搜索
。
有关使用信息,请参见
第12.9节“全文搜索功能”
。
InnoDB
FULLTEXT
索引在本节的以下主题中描述:
InnoDB
FULLTEXT
索引具有倒排索引设计。
反向索引存储单词列表,并为每个单词存储单词出现的文档列表。为了支持邻近搜索,还存储每个单词的位置信息,作为字节偏移量。
创建
InnoDB
FULLTEXT
索引时,会
创建
一组索引表,如以下示例所示:
MySQL的>CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200),
FULLTEXT idx (opening_line)
) ENGINE=InnoDB;
MySQL的>SELECT table_id, name, space from INFORMATION_SCHEMA.INNODB_TABLES
WHERE name LIKE 'test/%';
+ ---------- + -------------------------------------- -------------- + ------- + | table_id | 名字| 空间| + ---------- + -------------------------------------- -------------- + ------- + | 333 | test / fts_0000000000000147_00000000000001c9_index_1 | 289 | | 334 | test / fts_0000000000000147_00000000000001c9_index_2 | 290 | | 335 | test / fts_0000000000000147_00000000000001c9_index_3 | 291 | | 336 | test / fts_0000000000000147_00000000000001c9_index_4 | 292 | | 337 | test / fts_0000000000000147_00000000000001c9_index_5 | 293 | | 338 | test / fts_0000000000000147_00000000000001c9_index_6 | 294 | | 330 | test / fts_0000000000000147_being_deleted | 286 | | 331 | test / fts_0000000000000147_being_deleted_cache | 287 | | 332 | test / fts_0000000000000147_config | 288 | | 328 | test / fts_0000000000000147_deleted | 284 | | 329 | test / fts_0000000000000147_deleted_cache | 285 | | 327 | test / opening_lines | 283 | + ---------- + -------------------------------------- -------------- + ------- +
前六个表表示反向索引,称为辅助索引表。
当传入文档被标记化时,单个词(也称为
“
标记
”
)与位置信息和关联的文档ID(
DOC_ID
)
一起插入索引表中
。
根据单词第一个字符的字符集排序权重,对六个索引表中的单词进行完全排序和分区。
反向索引被划分为六个辅助索引表以支持并行索引创建。
默认情况下,两个线程对单词和关联数据进行标记,排序和插入索引表。
可以使用该
innodb_ft_sort_pll_degree
选项
配置线程数
。
FULLTEXT
在大型表上
创建
索引
时,请考虑增加线程数
。
辅助索引表名称带有前缀
fts_
和后缀
index_*
。
每个索引表都通过索引表名称中与
table_id
索引表
匹配的十六进制值与索引表相关联
。
例如,
table_id
所述的
test/opening_lines
表是
327
,为此,十六进制值是0x147。
如前面的示例所示,
“
147
”
十六进制值出现在与表关联的索引表的名称中
test/opening_lines
。
表示的十六进制值
index_id
的的
FULLTEXT
索引也出现在辅助索引表名。
例如,在辅助表名称中
test/fts_0000000000000147_00000000000001c9_index_1
,十六进制值
1c9
的十进制值为457.
可以通过查询
表中的值
来识别
opening_lines
table(
idx
)
上定义的索引
INFORMATION_SCHEMA.INNODB_INDEXES
(457)。
MySQL的>SELECT index_id, name, table_id, space from INFORMATION_SCHEMA.INNODB_INDEXES
WHERE index_id=457;
+ ---------- + ------ + ---------- + ------- + | index_id | 名字| table_id | 空间| + ---------- + ------ + ---------- + ------- + | 457 | idx | 327 | 283 | + ---------- + ------ + ---------- + ------- +
如果主表是在 每个表 的 文件表 空间中 创建的,则索引表存储在它们自己 的表 空间中。
前面示例中显示的其他索引表称为公共索引表,用于删除处理和存储
FULLTEXT
索引
的内部状态
。
与为每个全文索引创建的反向索引表不同,这组表对于在特定表上创建的所有全文索引是通用的。
即使删除了全文索引,也会保留公共辅助表。
删除全文索引时,将
FTS_DOC_ID
保留为索引创建的
FTS_DOC_ID
列
,因为删除
列将需要重建表。
管理
FTS_DOC_ID
色谱柱
需要常见的腋下表
。
fts_*_deleted
和
fts_*_deleted_cache
包含已删除但尚未从全文索引中删除其数据的文档的文档ID(DOC_ID)。
这
fts_*_deleted_cache
是
fts_*_deleted
表
的内存版本
。
fts_*_being_deleted
和
fts_*_being_deleted_cache
包含已删除文档的文档ID(DOC_ID),其数据当前正在从全文索引中删除。
该
fts_*_being_deleted_cache
表是表的内存版本
fts_*_being_deleted
。
fts_*_config
存储有关
FULLTEXT
索引
内部状态的信息
。
最重要的是,它存储了
FTS_SYNCED_DOC_ID
标识已解析并刷新到磁盘的文档。
在崩溃恢复的情况下,
FTS_SYNCED_DOC_ID
值用于标识尚未刷新到磁盘的文档,以便可以重新解析文档并将其添加回
FULLTEXT
索引缓存。
要查看此表中的数据,请查询该
INFORMATION_SCHEMA.INNODB_FT_CONFIG
表。
插入文档时,会对其进行标记化,并将单个单词和关联数据插入
FULLTEXT
索引中。
即使对于小型文档,此过程也可能导致在辅助索引表中进行大量小插入,从而使对这些表的并发访问成为争用的焦点。
要避免此问题,请
InnoDB
使用
FULLTEXT
索引缓存临时缓存最近插入的行的索引表插入。
此内存缓存结构保留插入,直到缓存已满,然后批量将它们刷新到磁盘(到辅助索引表)。
您可以查询该
INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE
表以查看最近插入的行的标记化数据。
缓存和批处理刷新行为避免了对辅助索引表的频繁更新,这可能导致繁忙的插入和更新时间期间的并发访问问题。 批处理技术还避免了对同一个单词的多次插入,并最大限度地减少了重复条目。 不是单独刷新每个单词,而是将同一个单词的插入合并并作为单个条目刷新到磁盘,从而提高插入效率,同时保持辅助索引表尽可能小。
该
innodb_ft_cache_size
变量用于配置全文索引缓存大小(基于每个表),这会影响全文索引缓存的刷新频率。
您还可以使用该
innodb_ft_total_cache_size
选项
为给定实例中的所有表定义全局全文索引缓存大小限制
。
全文索引缓存存储与辅助索引表相同的信息。 但是,全文索引缓存仅缓存最近插入的行的标记化数据。 已查询时,已刷新到磁盘(到全文辅助表)的数据不会返回到全文索引缓存中。 直接查询辅助索引表中的数据,并在返回之前将辅助索引表的结果与全文索引缓存的结果合并。
InnoDB
使用称为文档ID(
DOC_ID
)
的唯一文档标识符将
全文索引中的单词映射到单词出现的文档记录。
映射需要
FTS_DOC_ID
索引表上的列。
如果
FTS_DOC_ID
未定义
列,则在创建全文索引时
InnoDB
自动添加隐藏
FTS_DOC_ID
列。
以下示例演示了此行为。
以下表定义不包括
FTS_DOC_ID
列:
MySQL的>CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200)
) ENGINE=InnoDB;
使用
CREATE FULLTEXT INDEX
语法
在表上创建全文索引时,将
返回一个警告,报告
InnoDB
正在重建表以添加
FTS_DOC_ID
列。
MySQL的>CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
查询正常,0行受影响,1警告(0.19秒) 记录:0重复:0警告:1 MySQL的>SHOW WARNINGS;
+ --------- + ------ + -------------------------------- ------------------ + | 等级| 代码| 消息| + --------- + ------ + -------------------------------- ------------------ + | 警告| 124 | InnoDB重建表添加列FTS_DOC_ID | + --------- + ------ + -------------------------------- ------------------ +
使用
ALTER
TABLE
向没有
FTS_DOC_ID
列
的表添加全文索引
时,会返回相同的警告
。
如果您在
CREATE
TABLE
时间
创建全文索引
并且未指定
FTS_DOC_ID
列,则
InnoDB
添加隐藏
FTS_DOC_ID
列,而不发出警告。
定时
FTS_DOC_ID
列
定义
CREATE
TABLE
比在已加载数据的表上创建全文索引要便宜。
如果
FTS_DOC_ID
在加载数据之前在表上定义
了
列,则不必重建该表及其索引以添加新列。
如果您不关心
CREATE FULLTEXT
INDEX
性能,请忽略该
FTS_DOC_ID
列以便
InnoDB
为您创建它。
InnoDB
在
FTS_DOC_ID
列上
创建一个隐藏
列以及唯一索引(
FTS_DOC_ID_INDEX
)
FTS_DOC_ID
。
如果要创建自己的
FTS_DOC_ID
列,则必须将列定义为
BIGINT UNSIGNED NOT NULL
并命名
FTS_DOC_ID
(全部大写),如下例所示:
该
FTS_DOC_ID
列不需要定义为
AUTO_INCREMENT
列,但
AUTO_INCREMENT
可以使加载数据更容易。
MySQL的>CREATE TABLE opening_lines (
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200)
) ENGINE=InnoDB;
如果您选择自己定义
FTS_DOC_ID
列,则负责管理列以避免空值或重复值。
FTS_DOC_ID
值不能重用,这意味着
FTS_DOC_ID
值必须不断增加。
(可选)您可以
FTS_DOC_ID_INDEX
在
FTS_DOC_ID
列
上
创建所需的唯一
(全部大写)
。
MySQL的> CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on opening_lines(FTS_DOC_ID);
如果您不创建
FTS_DOC_ID_INDEX
,
InnoDB
则自动创建。
FTS_DOC_ID_INDEX
不能定义为降序索引,因为
InnoDB
SQL解析器不使用降序索引。
最大使用
FTS_DOC_ID
值与新
FTS_DOC_ID
值
之间的允许间隔
为65535。
为避免重建表,
FTS_DOC_ID
删除全文索引时将保留
该
列。
删除具有全文索引列的记录可能会导致辅助索引表中出现大量小删除,从而使这些表的并发访问成为争用的焦点。
为避免此问题,
每当从索引表中删除
DOC_ID
记录时,已删除文档
的文档ID(
)都会记录在特殊
FTS_*_DELETED
表中,并且索引记录将保留在全文索引中。
在返回查询结果之前,信息在
FTS_*_DELETED
table用于过滤掉已删除的文档ID。
这种设计的好处是删除快速且廉价。
缺点是删除记录后索引的大小不会立即减少。
要删除已删除记录的全文索引条目,请
OPTIMIZE TABLE
在索引表上
运行
innodb_optimize_fulltext_only=ON
以重建全文索引。
有关更多信息,请参阅
优化InnoDB全文索引
。
InnoDB
FULLTEXT
由于其缓存和批处理行为,索引具有特殊的事务处理特性。
具体而言,
FULLTEXT
在事务提交时处理索引
上的更新和插入
,这意味着
FULLTEXT
搜索只能看到已提交的数据。
以下示例演示了此行为。
该
FULLTEXT
搜索只返回插入的行被提交之后的结果。
MySQL的>CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200),
FULLTEXT idx (opening_line)
) ENGINE=InnoDB;
MySQL的>BEGIN;
MySQL的>INSERT INTO opening_lines(opening_line,author,title) VALUES
('Call me Ishmael.','Herman Melville','Moby-Dick'),
('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
('I am an invisible man.','Ralph Ellison','Invisible Man'),
('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
('It was love at first sight.','Joseph Heller','Catch-22'),
('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
MySQL的>SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+ ---------- + | COUNT(*)| + ---------- + | 0 | + ---------- + MySQL的>COMMIT;
MySQL的>SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+ ---------- + | COUNT(*)| + ---------- + | 1 | + ---------- +
您可以
InnoDB
FULLTEXT
通过查询以下
INFORMATION_SCHEMA
表
来监视和检查
索引
的特殊文本处理方面
:
您还可以
FULLTEXT
通过查询
INNODB_INDEXES
和
查看
索引和表的
基本信息
INNODB_TABLES
。
有关更多信息,请参见 第15.14.4节“InnoDB INFORMATION_SCHEMA FULLTEXT索引表” 。
本节介绍与
InnoDB
表空间
相关的主题
。
该
InnoDB
系统表空间的双写缓冲区和改变缓冲存储区。
系统表空间还包含在系统表空间中创建的用户创建表的表和索引数据。
在以前的版本中,系统表空间包含
InnoDB
数据字典。
在MySQL 8.0中,
InnoDB
将元数据存储在MySQL数据字典中。
请参见
第14章,
MySQL数据字典
。
系统表空间可以包含一个或多个数据文件。
默认情况下,
ibdata1
在数据目录中创建
一个名为的系统表空间数据文件
。
系统表空间数据文件的大小和数量由
innodb_data_file_path
启动选项
控制
。
有关相关信息,请参阅
系统表空间数据文件配置
。
本节介绍如何增大或减小
InnoDB
系统表空间
的大小
。
增加
InnoDB
系统表空间
大小的最简单方法
是从头开始配置它以自动扩展。
autoextend
在表空间定义中
指定
最后一个数据文件
的
属性。
然后
InnoDB
在空间不足时以64MB为增量自动增加该文件的大小。
可以通过设置
innodb_autoextend_increment
系统变量
的值来更改增量大小,该值
以兆字节为单位。
您可以通过添加另一个数据文件将系统表空间扩展一个定义的数量:
关闭MySQL服务器。
如果使用关键字定义了上一个最后一个数据文件
autoextend
,请根据实际增长的大小将其定义更改为使用固定大小。
检查数据文件的大小,将其向下舍入到1024×1024字节(= 1MB)的最接近倍数,并明确指定此舍入大小
innodb_data_file_path
。
添加新数据文件到末尾
innodb_data_file_path
,可选择使该文件自动扩展。
只能将最后一个数据文件
innodb_data_file_path
指定为自动扩展。
再次启动MySQL服务器。
例如,此表空间只有一个自动扩展数据文件
ibdata1
:
innodb_data_home_dir = innodb_data_file_path = / ibdata / ibdata1:10M:autoextend
假设这个数据文件随着时间的推移已增长到988MB。 以下是修改原始数据文件以使用固定大小并添加新的自动扩展数据文件后的配置行:
innodb_data_home_dir = innodb_data_file_path = / ibdata / ibdata1:988M; / disk2 / ibdata2:50M:autoextend
将新数据文件添加到系统表空间配置时,请确保文件名不引用现有文件。
InnoDB
重新启动服务器时创建并初始化文件。
您无法从系统表空间中删除数据文件。 要减小系统表空间大小,请使用以下过程:
使用
mysqldump
转储所有
InnoDB
表,包括
InnoDB
位于MySQL数据库中的表。
MySQL的> SELECT TABLE_NAME from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='mysql' and ENGINE='InnoDB';
+ --------------------------- +
| TABLE_NAME |
+ --------------------------- +
| columns_priv |
| 组件|
| db |
| default_roles |
| engine_cost |
| func |
| global_grants |
| gtid_executed |
| help_category |
| help_keyword |
| help_relation |
| help_topic |
| innodb_dynamic_metadata |
| innodb_index_stats |
| innodb_table_stats |
| 插件|
| procs_priv |
| proxies_priv |
| role_edges |
| server_cost |
| 服务器|
| slave_master_info |
| slave_relay_log_info |
| slave_worker_info |
| tables_priv |
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
| 用户|
+ --------------------------- +
停止服务器。
删除所有现有的表空间文件(
*.ibd
),包括
ibdata
和
ib_log
文件。
不要忘记删除
*.ibd
位于MySQL数据库中的表的文件。
配置新的表空间。
重启服务器。
导入转储文件。
如果您的数据库仅使用
InnoDB
引擎,则转储
所有
数据库,停止服务器,删除所有数据库和
InnoDB
日志文件,重新启动服务器以及导入转储文件
可能更简单
。
您可以将原始磁盘分区用作
InnoDB
系统表空间
中的数据文件
。
此技术可在Windows和某些Linux和Unix系统上启用非缓冲I / O,而无需文件系统开销。
使用和不使用原始分区执行测试以验证此更改是否实际上提高了系统性能。
使用原始磁盘分区时,请确保运行MySQL服务器的用户标识具有该分区的读写权限。
例如,如果以
mysql
用户
身份运行服务器
,则该分区必须是可读写的
mysql
。
如果使用该
--memlock
选项
运行服务器
,则必须运行服务器
root
,因此该分区必须是可读写的
root
。
下面描述的过程涉及选项文件修改。 有关其他信息,请参见 第4.2.2.2节“使用选项文件” 。
创建新数据文件时,请在
newraw
该
innodb_data_file_path
选项
的数据文件大小之后立即
指定关键字
。
分区必须至少与指定的大小一样大。
请注意,1MB in
InnoDB
是1024×1024字节,而磁盘规格中的1MB通常意味着1,000,000字节。
的[mysqld] innodb_data_home_dir = innodb_data_file_path中=的/ dev / HDD1:3Gnewraw;的/ dev / HDD2:2Gnewraw
重启服务器。
InnoDB
注意
newraw
关键字并初始化新分区。
但是,不要创建或更改任何
InnoDB
表。
否则,当您下次重新启动服务器时,
InnoDB
重新初始化分区并且您的更改将丢失。
(作为一种安全措施,
InnoDB
可防止用户在
newraw
指定
任何分区时修改数据
。)
在
InnoDB
初始化新分区后,停止服务器,
newraw
将数据文件规范
更改
为
raw
:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中=的/ dev / HDD1:3Graw;的/ dev / HDD2:2Graw
重启服务器。
InnoDB
现在允许进行更改。
在Windows系统上,适用于Linux和Unix系统的相同步骤和附带指南适用,但
innodb_data_file_path
Windows上
的
设置稍有不同。
创建新数据文件时,请在
newraw
该
innodb_data_file_path
选项
的数据文件大小之后立即
指定关键字
:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中= //。/ d :: 10Gnewraw
该
//./
对应于Windows的语法
\\.\
来访问物理驱动器。
在上面的示例中,
D:
是分区的驱动器号。
重启服务器。
InnoDB
注意
newraw
关键字并初始化新分区。
在
InnoDB
初始化新分区后,停止服务器,
newraw
将数据文件规范
更改
为
raw
:
的[mysqld] innodb_data_home_dir = innodb_data_file_path中= //。/ d :: 10Graw
重启服务器。
InnoDB
现在允许进行更改。
从历史上看,
InnoDB
表存储在
系统表空间中
。
这种单片方法针对专用于数据库处理的机器,精心规划数据增长,其中任何分配给MySQL的磁盘存储都不会用于其他目的。
每个表
的
文件表空间
功能提供了更灵活的替代方案,其中每个
InnoDB
表都存储在自己的表空间数据文件(
.ibd
文件)中。
此功能由
innodb_file_per_table
配置选项
控制
,默认情况下启用
该
选项。
截断或删除存储在每个表文件表空间中的表时,可以回收磁盘空间。
截断或删除存储在共享
系统表空间中的表
会在系统表空间数据文件(
ibdata文件
)
内部创建可用空间,该数据文件
只能用于新
InnoDB
数据。
类似地,
ALTER
TABLE
驻留在共享表空间中的表上的表
复制
操作可以增加表空间使用的空间量。
此类操作可能需要与表中的数据和索引一样多的额外空间。
表复制
ALTER
TABLE
操作
所需的额外空间
不会像文件每表表空间一样释放回操作系统。
TRUNCATE TABLE
在存储在每个表文件表空间中的表上运行时
,
操作更快。
您可以通过使用语法指定每个表的位置,将特定表存储在单独的存储设备上,进行I / O优化,空间管理或备份
,如
第15.6.3.6节“在数据目录外创建表空间”中所述“
。
CREATE TABLE ... DATA DIRECTORY =
absolute_path_to_directory
您可以运行
OPTIMIZE
TABLE
以压缩或重新创建每个表的文件表空间。
当您运行
OPTIMIZE
TABLE
,
InnoDB
创建一个新的
.ibd
具有临时名称的文件,只使用存储的实际数据所需的空间。
优化完成后,
InnoDB
删除旧
.ibd
文件并将其替换为新文件。
如果前一个
.ibd
文件显着增长但实际数据仅占其大小的一部分,则运行
OPTIMIZE
TABLE
可以回收未使用的空间。
您可以移动单个
InnoDB
表而不是整个数据库。
您可以将单个
InnoDB
表从一个MySQL实例
复制
到另一个MySQL实例(称为可
传输表空间
功能)。
您可以
使用
动态行格式
为具有大型
BLOB
或
TEXT
列的
表启用更高效的存储
。
每个表的文件表空间可以提高成功恢复的机会,并在发生损坏,无法重新启动服务器或备份和二进制日志不可用时节省时间。
您可以使用MySQL Enterprise Backup产品快速备份或还原单个表,而不会中断其他
InnoDB
表
的使用
。
如果您的表需要较少的备份或不同的备份计划,这将非常有用。
有关
详细信息,
请参阅
进行部分备份
。
在复制或备份表时,每表文件表空间便于每表状态报告。
您可以在不访问MySQL的情况下监视文件系统级别的表大小。
当
innodb_flush_method
设置为
常用Linux文件系统时,不允许对单个文件进行并发写入
O_DIRECT
。
因此,在结合使用每表文件表空间时,可能会有性能提升
innodb_flush_method
。
系统表空间存储数据字典和撤消日志,并且受
InnoDB
表空间大小限制的限制。
请参见
第15.6.1.6节“InnoDB表的限制”
。
使用每表文件表空间,每个表都有自己的表空间,这为增长提供了空间。
对于每个表的文件表空间,每个表可能有未使用的空间,只能由同一个表的行使用。 如果管理不当,这可能会导致空间浪费。
fsync
操作必须在每个打开的表上运行,而不是在单个文件上运行。
由于
fsync
每个文件
都有单独的
操作,因此不能将多个表上的写操作组合到单个I / O操作中。
这可能需要
InnoDB
执行更高的
fsync
操作
总数
。
mysqld 必须为每个表保留一个打开的文件句柄,如果在每个表的文件表空间中有许多表,这可能会影响性能。
使用更多文件描述符。
innodb_file_per_table
在MySQL 5.6及更高版本中默认启用。
如果与早期版本的MySQL向后兼容是一个问题,您可以考虑禁用它。
如果许多表正在增长,则可能存在更多碎片,这可能会妨碍
DROP
TABLE
表扫描性能。
但是,在管理碎片时,在自己的表空间中放置文件可以提高性能。
删除每个表的文件表空间时会扫描缓冲池,对于数十GB的缓冲池,这可能需要几秒钟。 使用广泛的内部锁执行扫描,这可能会延迟其他操作。 系统表空间中的表不受影响。
该
innodb_autoextend_increment
变量定义了增量大小(以MB为单位),用于在自动扩展的共享表空间文件变满时扩展其大小,不适用于每个表文件的表空间文件,无论
innodb_autoextend_increment
设置
如何,这些文件都是自动扩展的
。
初始扩展是少量的,之后扩展以4MB的增量发生。
innodb_file_per_table
默认情况下启用
该
选项。
要
innodb_file_per_table
在启动时
设置
选项,请使用
--innodb_file_per_table
命令行选项
启动服务器
,或将此行添加到以下
[mysqld]
部分
my.cnf
:
的[mysqld] innodb_file_per_table = 1
您还可以
innodb_file_per_table
在服务器运行时动态
设置
:
MySQL的> SET GLOBAL innodb_file_per_table=1;
与
innodb_file_per_table
启用,可以存储
InnoDB
在一个表
文件。
不同于
tbl_name
.ibdMyISAM
存储引擎,与它的独立
和
tbl_name
.MYD
文件进行索引和数据,
tbl_name
.MYIInnoDB
在一个单一的数据和索引存储在一起
.ibd
的文件。
如果
innodb_file_per_table
在启动选项中
禁用
并重新启动服务器,或使用该
SET GLOBAL
命令
禁用它,则
InnoDB
在系统表空间内创建新表,除非您已使用该
CREATE
TABLE ...
TABLESPACE
选项
将表显式放置在每表文件表空间或通用表空间中
。
InnoDB
无论每个表的文件设置如何,
您始终可以读写任何
表。
要将表从系统表空间移动到其自己的表空间,请更改
innodb_file_per_table
设置并重建表:
mysql>SET GLOBAL innodb_file_per_table=1;
mysql>ALTER TABLE
table_name
ENGINE=InnoDB;
使用
CREATE
TABLE ...
TABLESPACE
或
ALTER
TABLE ...
TABLESPACE
语法
添加到系统表空间的表
不受
innodb_file_per_table
设置的
影响
。
要将这些表从系统表空间移动到每个表的文件表空间,必须使用
ALTER
TABLE ...
TABLESPACE
语法
显式移动它们
。
InnoDB
总是需要系统表空间,因为它将内部
数据字典
和
撤消日志
放在
那里。
这些
.ibd
文件不足以
InnoDB
运行。
将表从系统表空间移出到其自己的
.ibd
文件中时,组成系统表空间的数据文件大小保持不变。
以前由表占用的空间可以重新用于新
InnoDB
数据,但不会被回收以供操作系统使用。
将大
InnoDB
表移出磁盘空间有限的系统表空间时,您可能更喜欢
innodb_file_per_table
使用
mysqldump
命令
启用
并重新创建整个实例
。
如上所述,使用
CREATE TABLE ...
TABLESPACE
或
ALTER
TABLE ...
TABLESPACE
语法
添加到系统表空间的表
不受
innodb_file_per_table
设置。
必须单独移动这些表。
通用表空间是
InnoDB
使用
CREATE
TABLESPACE
语法
创建
的共享
表空间
。
本节中的以下主题描述了常规表空间功能和功能:
通用表空间功能提供以下功能:
与系统表空间类似,通用表空间是可以存储多个表的数据的共享表空间。
与基于 文件的表空间 相比,常规表空间具有潜在的内存优势 。 服务器在表空间的生命周期内将表空间元数据保存在内存中。 较少的通用表空间中的多个表对表空间元数据的内存消耗比单独的每个表文件表空间中的相同数量的表少。
通用表空间数据文件可以放在相对于MySQL数据目录或独立于MySQL数据目录的目录中,该目录为您提供了 每个表文件表空间的 许多数据文件和存储管理功能 。 与每表文件表空间一样,将数据文件放在MySQL数据目录之外的功能允许您分别管理关键表的性能,为特定表设置RAID或DRBD,或者将表绑定到特定磁盘。
常规表空间支持Antelope和Barracuda文件格式,因此支持所有表格行格式和相关功能。
由于支持这两种文件格式,一般表空间不依赖于
innodb_file_format
或
innodb_file_per_table
设置,这些变量也不会对一般表空间产生任何影响。
该
TABLESPACE
选项可用于
CREATE TABLE
在通用表空间,每表文件表空间或系统表空间中创建表。
该
TABLESPACE
选项可用于
ALTER
TABLE
在常规表空间,每表文件表空间和系统表空间之间移动表。
以前,无法将表从每个表的文件表空间移动到系统表空间。
使用常规表空间功能,您现在可以执行此操作。
使用
CREATE TABLESPACE
语法
创建常规表空间
。
CREATE TABLESPACEtablespace_name
[添加数据文件'file_name
'] [FILE_BLOCK_SIZE =value
] [ENGINE [=]engine_name
]
可以在数据目录中或在其外部创建常规表空间。
为避免与隐式创建的每表文件表空间冲突,不支持在数据目录下的子目录中创建常规表空间。
在数据目录之外创建通用表空间时,该目录必须存在,并且必须
InnoDB
在创建表空间之前
知道
。
要创建已知的未知目录
InnoDB
,请将该目录添加到
innodb_directories
参数值。
innodb_directories
是一个只读启动选项。
配置它需要重新启动服务器。
例子:
在数据目录中创建常规表空间:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
要么
MySQL的> CREATE TABLESPACE `ts1` Engine=InnoDB;
该
ADD DATAFILE
子句在MySQL 8.0.14中是可选的,在此之前是必需的。
如果
ADD
DATAFILE
在创建表空间时未指定子句,则会隐式创建具有唯一文件名的表空间数据文件。
唯一文件名是128位UUID,格式化为由破折号(
aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
)
分隔的五组十六进制数字
。
常规表空间数据文件包括
.ibd
文件扩展名。
在复制环境中,在主服务器上创建的数据文件名与在从服务器上创建的数据文件名不同。
在数据目录之外的目录中创建常规表空间:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;
只要表空间目录不在数据目录下,就可以指定相对于数据目录的路径。
在此示例中,
my_tablespace
目录与数据目录处于同一级别:
MySQL的> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd' Engine=InnoDB;
该
ENGINE = InnoDB
子句必须定义为
CREATE
TABLESPACE
语句的
一部分
,或者
InnoDB
必须定义为默认存储引擎(
default_storage_engine=InnoDB
)。
创建
InnoDB
通用表空间后,可以使用
或
向表空间添加表,如以下示例所示:
CREATE
TABLE
tbl_name
... TABLESPACE [=]
tablespace_name
ALTER TABLE
tbl_name
TABLESPACE [=]
tablespace_name
MySQL的> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1;
MySQL的> ALTER TABLE t2 TABLESPACE ts1;
在MySQL 5.7.24中不支持将表分区添加到共享表空间,并在MySQL 8.0.13中删除了。
共享表空间包括
InnoDB
系统表空间和通用表空间。
有关详细语法信息,请参阅
CREATE
TABLE
和
ALTER
TABLE
。
一般的表空间支持所有表行格式(
REDUNDANT
,
COMPACT
,
DYNAMIC
,
COMPRESSED
)与压缩和非压缩表不能在同一个表空间一般共存的警告,由于不同的物理页面大小。
对于包含压缩表(
ROW_FORMAT=COMPRESSED
)
的常规表空间
,
FILE_BLOCK_SIZE
必须指定,并且该
FILE_BLOCK_SIZE
值必须是
与该
值相关的有效压缩页大小
innodb_page_size
。
此外,压缩表(
KEY_BLOCK_SIZE
)
的物理页面大小
必须等于
FILE_BLOCK_SIZE/1024
。
例如,如果
innodb_page_size=16KB
和
FILE_BLOCK_SIZE=8K
,
KEY_BLOCK_SIZE
表的必须为8。
下表显示了允许的
innodb_page_size
,
FILE_BLOCK_SIZE
和
KEY_BLOCK_SIZE
组合。
FILE_BLOCK_SIZE
值也可以以字节为单位指定。
要确定
KEY_BLOCK_SIZE
给定
的有效值
FILE_BLOCK_SIZE
,请将
FILE_BLOCK_SIZE
值除以1024.表压缩不支持32K和64K
InnoDB
页面大小。
有关的更多信息
KEY_BLOCK_SIZE
,请参见
CREATE
TABLE
和
第15.9.1.2节“创建压缩表”
。
表15.4压缩表的允许页大小,FILE_BLOCK_SIZE和KEY_BLOCK_SIZE组合
InnoDB页面大小(innodb_page_size) | 允许的FILE_BLOCK_SIZE值 | 允许的KEY_BLOCK_SIZE值 |
---|---|---|
64KB | 64K(65536) | 不支持压缩 |
32KB | 32K(32768) | 不支持压缩 |
16KB | 16K(16384) |
N / A:如果
innodb_page_size
等于
FILE_BLOCK_SIZE
,则表空间不能包含压缩表。
|
16KB | 8K(8192) | 8 |
16KB | 4K(4096) | 4 |
16KB | 2K(2048) | 2 |
16KB | 1K(1024) | 1 |
8KB | 8K(8192) |
N / A:如果
innodb_page_size
等于
FILE_BLOCK_SIZE
,则表空间不能包含压缩表。
|
8KB | 4K(4096) | 4 |
8KB | 2K(2048) | 2 |
8KB | 1K(1024) | 1 |
4KB | 4K(4096) |
N / A:如果
innodb_page_size
等于
FILE_BLOCK_SIZE
,则表空间不能包含压缩表。
|
4KB | 2K(2048) | 2 |
4KB | 1K(1024) | 1 |
此示例演示如何创建常规表空间并添加压缩表。
该示例假定默认
innodb_page_size
值为16KB。
在
FILE_BLOCK_SIZE
8192要求压缩表有
KEY_BLOCK_SIZE
8个。
MySQL的>CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
MySQL的>CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
如果未指定
FILE_BLOCK_SIZE
何时创建常规表空间,则
FILE_BLOCK_SIZE
默认为
innodb_page_size
。
当
FILE_BLOCK_SIZE
等于
innodb_page_size
,表空间可能只包含与未压缩的行格式(表
COMPACT
,
REDUNDANT
和
DYNAMIC
行格式)。
您可以使用
ALTER
TABLE
该
TABLESPACE
选项将表移动到现有的通用表空间,新的每个表文件表空间或系统表空间。
在MySQL 5.7.24中不支持在共享表空间中放置表分区,并删除了MySQL 8.0.13。
共享表空间包括
InnoDB
系统表空间和通用表空间。
要将表从每个表的文件表空间或从系统表空间移动到常规表空间,请指定常规表空间的名称。
通用表空间必须存在。
有关
CREATE TABLESPACE
更多信息,
请参阅
ALTER TABLE tbl_name TABLESPACE [=] tablespace_name
;
要将表从通用表空间或每表文件表空间移动到系统表空间,请指定
innodb_system
为表空间名称。
ALTER TABLE tbl_name TABLESPACE [=] innodb_system;
要将表从系统表空间或通用表空间移动到每个表的文件表空间,请指定
innodb_file_per_table
为表空间名称。
ALTER TABLE tbl_name TABLESPACE [=] innodb_file_per_table;
ALTER TABLE ... TABLESPACE
即使
TABLESPACE
属性未从其先前值更改,
操作也始终会导致完整表重建
。
ALTER TABLE ... TABLESPACE
语法不支持将表从临时表空间移动到持久表空间。
该
DATA DIRECTORY
条款是允许的,
CREATE TABLE ...
TABLESPACE=innodb_file_per_table
但不支持与该
TABLESPACE
选项一起使用。
从加密表空间移动表时适用限制。 请参阅 加密限制 。
使用
ALTER
TABLESPACE ... RENAME TO
语法
支持重命名通用表空间
。
ALTER TABLESPACE s1重命名为s2;
CREATE TABLESPACE
重命名常规表空间需要
该
权限。
RENAME TO
autocommit
无论
autocommit
设置
如何,
都以
模式
隐式执行操作
。
甲
RENAME TO
操作不能同时被执行
LOCK TABLES
或者
FLUSH
TABLES WITH READ
LOCK
是在驻留在表空间的表的效果。
在重命名表空间时,会对通用表空间中的表执行 独占 元数据锁定 ,从而防止并发DDL。 支持并发DML。
该
DROP TABLESPACE
语句用于删除
InnoDB
常规表空间。
必须在
DROP TABLESPACE
操作
之前从表空间中删除所有表
。
如果表空间不为空,则
DROP
TABLESPACE
返回错误。
使用类似于以下内容的查询来标识常规表空间中的表。
MySQL的>SELECT a.NAME AS space_name, b.NAME AS table_name FROM INFORMATION_SCHEMA.INNODB_TABLESPACES a,
INFORMATION_SCHEMA.INNODB_TABLES b WHERE a.SPACE=b.SPACE AND a.NAME LIKE 'ts1';
+ ------------ + ------------ + | space_name | table_name | + ------------ + ------------ + | ts1 | test / t1 | | ts1 | test / t2 | | ts1 | test / t3 | + ------------ + ------------ +
InnoDB
删除表空间中的最后一个表时,不会自动删除
常规
表空间。
必须使用显式删除表空间
。
DROP TABLESPACE
tablespace_name
通用表空间不属于任何特定数据库。
一个
DROP DATABASE
操作可以丢弃属于一般的表空间的表,但它不能删除表空间,即使
DROP
DATABASE
操作下降属于该表空间中的所有表。
必须使用显式删除常规表空间
。
DROP
TABLESPACE
tablespace_name
与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间
.ibd数据文件
内部创建可用空间,该
文件
只能用于新
InnoDB
数据。
空间不会释放回操作系统,因为在
DROP
TABLE
操作
期间删除了每表文件表空间
。
此示例演示如何删除
InnoDB
常规表空间。
ts1
使用单个表创建
常规表空间
。
在删除表空间之前必须删除该表。
MySQL的>CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;
MySQL的>DROP TABLE t1;
MySQL的>DROP TABLESPACE ts1;
是MySQL中区分大小写的标识符。
tablespace_name
生成的或现有的表空间不能更改为常规表空间。
不支持创建临时通用表空间。
常规表空间不支持临时表。
与系统表空间类似,截断或删除存储在通用表空间中的表会在通用表空间
.ibd数据文件
内部创建可用空间,该
文件
只能用于新
InnoDB
数据。
空间不会像
文件每表表
空间
一样释放回操作系统
。
此外,
ALTER
TABLE
驻留在共享表空间(通用表空间或系统表空间)中的表上的表
复制
操作可以增加表空间使用的空间量。
此类操作需要与表中的数据和索引一样多的额外空间。
表复制
ALTER
TABLE
操作
所需的额外空间
不会像文件每表表空间一样释放回操作系统。
ALTER
TABLE ...
DISCARD TABLESPACE
并且
ALTER
TABLE
...IMPORT TABLESPACE
不支持属于常规表空间的表。
支持在一般表空间中放置表分区在MySQL 5.7.24中已弃用,在MySQL 8.0.13中已删除。
撤消表空间包含撤消日志,撤消日志是撤消日志记录的集合,其中包含有关如何撤消事务到聚簇索引记录的最新更改的信息。
撤消日志存在于撤消日志段中,这些日志段包含在回滚段中。
该
innodb_rollback_segments
变量定义分配给每个撤消表空间的回滚段数。
初始化MySQL实例时会创建两个默认的撤消表空间。 在初始化时创建默认的撤消表空间,以便为可以接受SQL语句之前必须存在的回滚段提供位置。 至少需要两个撤消表空间才能支持自动截断撤消表空间。 请参阅 截断撤消表空间 。
在
innodb_undo_directory
变量
定义的位置创建默认的撤消表空间
。
如果
innodb_undo_directory
变量未定义,则在数据目录中创建默认的撤消表空间。
默认的undo表空间数据文件名为
undo_001
and
undo_002
。
数据字典中定义的相应撤消表空间名称是
innodb_undo_001
和
innodb_undo_002
。
从MySQL 8.0.14开始,可以使用SQL在运行时创建其他撤消表空间。 请参阅 添加撤消表空间 。
undo表空间数据文件的初始大小取决于
innodb_page_size
值。
对于默认的16KB页面大小,初始撤消表空间文件大小为10MiB。
对于4KB,8KB,32KB和64KB页面大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。
由于在长时间运行的事务期间撤消日志可能会变大,因此创建其他撤消表空间可以帮助防止单个撤消表空间变得过大。
从MySQL 8.0.14开始,可以使用
CREATE UNDO
TABLESPACE
语法
在运行时创建其他撤消表空间
。
创建UNDO TABLESPACEtablespace_name
添加数据文件'file_name
.ibu'
撤消表空间文件名必须具有
.ibu
扩展名。
在定义撤消表空间文件名时,不允许指定相对路径。
允许使用完全限定的路径,但必须知道路径
InnoDB
。
已知路径是由
innodb_directories
变量
定义的路径
。
在启动时,
innodb_directories
将扫描变量
定义的目录以
获取撤消表空间文件。
(扫描也横穿子目录。)由定义的目录
innodb_data_home_dir
,
innodb_undo_directory
和
datadir
变量被自动添加到
innodb_directories
值,而不管是否
innodb_directories
变量被明确定义。
因此,撤消表空间可以驻留在由任何这些变量定义的路径中。
如果undo表空间文件名不包含路径,则会在
innodb_undo_directory
变量
定义的目录中创建undo表空间
。
如果未定义该变量,则会在数据目录中创建撤消表空间。
在
InnoDB
恢复过程要求撤销表空间文件驻留在已知的目录。
必须在重做恢复之前和打开其他数据文件之前发现并打开撤消表空间文件,以允许回滚未提交的事务和数据字典更改。
无法使用恢复前未找到的撤消表空间,这可能导致数据库不一致。
如果未找到数据字典已知的撤消表空间,则在启动时会报告错误消息。
已知的目录要求还支持撤消表空间可移植性。
请参阅
移动撤消表空间
。
要在相对于数据目录的路径中创建撤消表空间,请将
innodb_undo_directory
变量设置为相对路径,并仅在创建撤消表空间时指定文件名。
要查看撤消表空间名称和路径,请查询
INFORMATION_SCHEMA.FILES
:
来自INFORMATION_SCHEMA.FILES的SELECT TABLESPACE_NAME,FILE_NAME FILE_TYPE喜欢'UNDO LOG';
MySQL实例最多支持127个undo表空间,包括MySQL实例初始化时创建的两个默认undo表空间。
在MySQL 8.0.14之前,通过配置
innodb_undo_tablespaces
启动变量
来创建其他撤消表空间
。
不推荐使用此变量,不再可以从MySQL 8.0.14开始配置。
在MySQL 8.0.14之前,增加
innodb_undo_tablespaces
设置会创建指定数量的撤消表空间,并将它们添加到活动撤消表空间列表中。
减小
innodb_undo_tablespaces
设置会从活动的撤消表空间列表中删除撤消表空间。
从活动列表中删除的撤消表空间保持活动状态,直到现有事务不再使用它们。
所述
innodb_undo_tablespaces
变量可以在运行时使用一被配置
SET
陈述或在配置文件中定义。
在MySQL 8.0.14之前,无法删除已停用的撤消表空间。
在缓慢关闭后可以手动删除撤消表空间文件但不建议这样做,因为如果在关闭服务器时存在打开的事务,则在重新启动服务器后的一段时间内,停用的撤消表空间可能包含活动的撤消日志。
从MySQL 8.0.14开始,可以使用
DROP UNDO
TABALESPACE
语法
删除撤消表空间
。
请参阅
删除撤消表空间
。
从MySQL 8.0.14开始,
CREATE UNDO
TABLESPACE
可以
使用
语法在运行时删除
使用
语法
创建的撤消表空间
DROP UNDO
TABALESPACE
。
撤消表空间在删除之前必须为空。
要清空撤消表空间,必须首先使用
ALTER UNDO
TABLESPACE
语法
将撤消表空间标记为非活动,
以便不再使用表空间将回滚段分配给新事务。
ALTER UNDO TABLESPACE tablespace_name
SET INACTIVE;
将撤消表空间标记为非活动后,允许完成当前在撤消表空间中使用回滚段的事务,以及在这些事务完成之前启动的任何事务。 事务完成后,清除系统将释放撤消表空间中的回滚段,并将撤消表空间截断为其初始大小。 (截断撤消表空间时使用相同的过程。请参阅 截断撤消表空间 。)当撤消表空间为空时,可以删除它。
DROP UNDO TABLESPACE tablespace_name
;
或者,撤消表空间可以保留为空状态,并在需要时通过发出
语句
稍后重新激活
。
ALTER UNDO
TABLESPACE
tablespace_name
SET
ACTIVE
可以通过查询
INFORMATION_SCHEMA.INNODB_TABLESPACES
表
来监视撤消表空间的状态
。
SELECT NAME,STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
名称在哪里tablespace_name
;
的
inactive
状态表示在撤销表空间回滚段不再使用新的交易。
一个
empty
状态指示UNDO表空间是空的,并准备好被丢弃或再使用作出了积极
发言。
尝试删除非空的撤消表空间会返回错误。
ALTER UNDO
TABLESPACE
tablespace_name
SET
ACTIVE
无法删除MySQL实例初始化时创建
的默认撤消表空间(
innodb_undo_001
和
innodb_undo_002
)。
但是,可以使用
声明
使它们处于非活动状态
。
在默认撤消表空间可以处于非活动状态之前,必须有一个撤消表空间来取代它。
始终至少需要两个活动的撤消表空间,以支持自动截断撤消表空间。
ALTER UNDO
TABLESPACE
tablespace_name
SET
INACTIVE
使用
CREATE UNDO
TABLESPACE
语法
创建的撤消表空间
可以在服务器脱机时移动到任何已知目录。
已知目录是由
innodb_directories
变量
定义的目录
。
无论是否
明确定义变量
,
由
innodb_data_home_dir
,
定义的目录
innodb_undo_directory
,以及
datadir
自动附加到
innodb_directories
值的目录
innodb_directories
。
在启动时扫描这些目录及其子目录以获取撤消表空间文件。
在启动时发现移动到任何这些目录的撤消表空间文件,并假定它是已移动的撤消表空间。
初始化MySQL实例时创建
的默认撤消表空间(
innodb_undo_001
和
innodb_undo_002
)必须始终位于
innodb_undo_directory
变量
定义的目录中
。
如果
innodb_undo_directory
变量未定义,则默认的undo表空间将驻留在数据目录中。
如果在服务器脱机时移动了默认的撤消表空间,则必须使用
innodb_undo_directory
配置到新目录
的
变量
启动服务器
。
撤消日志的I / O模式使撤消表空间成为 SSD 存储的 良好候选者 。
该
innodb_rollback_segments
变量定义
分配给每个撤消表空间和全局临时表空间
的
回滚段
数
。
该
innodb_rollback_segments
变量可以在启动时被配置为或在服务器正在运行。
默认设置为
innodb_rollback_segments
128,也是最大值。
有关回滚段支持的事务数的信息,请参见
第15.6.6节“撤消日志”
。
有两种截断撤消表空间的方法,可以单独使用或组合使用来管理撤消表空间大小。 一种方法是自动化的,使用配置变量启用。 另一种方法是手动,使用SQL语句执行。
自动方法不需要监视撤消表空间大小,并且一旦启用,它就会执行撤消,截断和重新激活撤消表空间,而无需手动干预。 如果要控制撤消表空间何时脱机以进行截断,则手动截断方法可能更为可取。 例如,您可能希望避免在高峰工作负载时间截断撤消表空间。
undo表空间的自动截断至少需要两个活动的undo表空间,这样可以确保一个undo表空间保持活动状态,而另一个表空间处于脱机状态以进行截断。 缺省情况下,MySQL实例初始化时会创建两个undo表空间。
要自动截断撤消表空间,请启用该
innodb_undo_log_truncate
变量。
例如:
MySQL的> SET GLOBAL innodb_undo_log_truncate=ON;
当
innodb_undo_log_truncate
被使能可变的,撤消超过由所定义的大小限制表空间
innodb_max_undo_log_size
变量受到截断。
该
innodb_max_undo_log_size
变量是动态的,默认值为1073741824字节(1024 MiB)。
MySQL的> SELECT @@innodb_max_undo_log_size;
+ ---------------------------- +
| @@ innodb_max_undo_log_size |
+ ---------------------------- +
| 1073741824 |
+ ---------------------------- +
当
innodb_undo_log_truncate
启用变量:
超出
innodb_max_undo_log_size
设置的
默认和用户定义的撤消表空间
标记为截断。
选择用于截断的撤消表空间以循环方式执行,以避免每次都截断相同的撤消表空间。
驻留在所选撤消表空间中的回滚段将变为非活动状态,以便不将它们分配给新事务。 允许当前使用回滚段的现有事务完成。
该 净化 系统释放回滚段不再使用。
释放撤消表空间中的所有回滚段后,将运行truncate操作并将undo表空间截断为其初始大小。
undo表空间的初始大小取决于
innodb_page_size
值。
对于默认的16KB页面大小,初始撤消表空间文件大小为10MiB。
对于4KB,8KB,32KB和64KB页面大小,初始撤消表空间文件大小分别为7MiB,8MiB,20MiB和40MiB。
由于在操作完成后立即使用,截断操作之后的撤消表空间的大小可能大于初始大小。
该
innodb_undo_directory
变量定义了默认undo表空间文件的位置。
如果
innodb_undo_directory
变量未定义,则默认的undo表空间将驻留在数据目录中。
CREATE
UNDO TABLESPACE
可以通过查询
INFORMATION_SCHEMA.FILES
表
来确定
所有撤消表空间文件的位置,包括使用
语法
创建的用户定义的撤消表空间
:
SELECT TABLESPACE_NAME,FILE_NAME来自INFORMATION_SCHEMA.FILES,其中FILE_TYPE喜欢'UNDO LOG';
重新激活回滚段,以便将它们分配给新事务。
手动截断撤消表空间至少需要三个活动的撤消表空间。 始终需要两个活动的撤消表空间,以支持启用自动截断的可能性。 至少有三个撤消表空间满足此要求,同时允许撤消表空间手动脱机。
要手动启动撤消表空间的截断,请通过发出以下语句来停用撤消表空间:
ALTER UNDO TABLESPACE tablespace_name
SET INACTIVE;
将撤消表空间标记为非活动后,允许完成当前在撤消表空间中使用回滚段的事务,以及在这些事务完成之前启动的任何事务。
事务完成后,清除系统释放撤消表空间中的回滚段,撤消表空间被截断为其初始大小,撤消表空间状态从更改
inactive
为
empty
。
当
语句停用撤消表空间时,清除线程会在下次机会时查找该撤消表空间。
找到撤消表空间并标记为截断后,清除线程将以更高的频率返回,以快速清空并截断撤消表空间。
ALTER UNDO TABLESPACE
tablespace_name
SET
INACTIVE
要检查撤消表空间的状态,请查询该
INFORMATION_SCHEMA.INNODB_TABLESPACES
表。
SELECT NAME,STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES
名称在哪里tablespace_name
;
一旦撤消表空间处于某种
empty
状态,就可以通过发出以下语句来重新激活它:
ALTER UNDO TABLESPACE tablespace_name
SET ACTIVE;
empty
还可以删除状态中
的撤消表空间
。
请参阅
删除撤消表空间
。
清除线程负责清空和截断撤消表空间。
默认情况下,清除线程会查找撤消表空间,以便每调用一次清除128次就会截断一次。
清除线程查找撤消表空间以进行截断的频率由
innodb_purge_rseg_truncate_frequency
变量
控制,该
变量的默认设置为128。
MySQL的> SELECT @@innodb_purge_rseg_truncate_frequency;
+ ---------------------------------------- +
| @@ innodb_purge_rseg_truncate_frequency |
+ ---------------------------------------- +
| 128 |
+ ---------------------------------------- +
要增加该频率,请减小
innodb_purge_rseg_truncate_frequency
设置。
例如,要让purge线程每隔32个调用purge的时间一次查找undo tabespaces,设置
innodb_purge_rseg_truncate_frequency
为32。
MySQL的> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
当清除线程找到需要截断的撤消表空间时,清除线程以更高的频率返回,以快速清空并截断撤消表空间。
撤消撤消表空间时,撤消表空间中的回滚段将被停用。 其他撤消表空间中的活动回滚段承担整个系统负载的责任,这可能会导致性能略有下降。 性能下降的程度取决于许多因素:
撤消表空间的数量
撤消日志数
撤消表空间大小
I / O susbsystem的速度
现有的长期运行事务
系统负载
截断撤消表空间时避免影响性能的最简单方法是增加撤消表空间的数量。
在MySQL 8.0.16中,
undo
和
purge
susbsystem计数器提供用于监视与撤销日志截断相关的后台活动。
对于计数器名称和描述,请查询该
INFORMATION_SCHEMA.INNODB_METRICS
表。
选择名称,子系统,来自INFORMATION_SCHEMA.INNODB_METRICS的评论,其中名称类似'%truncate%';
有关启用计数器和查询计数器数据的信息,请参见 第15.14.6节“InnoDB INFORMATION_SCHEMA度量表” 。
InnoDB
使用会话临时表空间和全局临时表空间。
会话临时表空间存储由优化程序创建的用户创建的临时表和内部临时表,当
InnoDB
配置为磁盘内部临时表的存储引擎时。
从MySQL 8.0.16开始,始终使用用于磁盘内部临时表的存储引擎
InnoDB
。
(以前,存储引擎是由值决定的
internal_tmp_disk_storage_engine
。)
会话临时表空间在第一个请求中从临时表空间池分配给会话,以创建磁盘上的临时表。
最多两个表空间分配给一个会话,一个用于用户创建的临时表,另一个用于由优化器创建的内部临时表。
分配给会话的临时表空间用于会话创建的所有磁盘上临时表。
会话断开连接时,其临时表空间将被截断并释放回池中。
启动服务器时,将创建一个包含10个临时表空间的池。
池的大小永远不会缩小,并且表空间会根据需要自动添加到池中。
临时表空间池在正常关闭或中止初始化时被删除。
会话临时表空间文件在创建时大小为五页,并且具有
.ibt
文件扩展名。
为会话临时表空间保留了40万个空间ID。 由于每次启动服务器时都会重新创建会话临时表空间池,因此当服务器关闭并且可以重用时,会话临时表空间的空间ID不会保留。
该
innodb_temp_tablespaces_dir
变量定义创建会话临时表空间的位置。
默认位置是
#innodb_temp
数据目录中的目录。
如果无法创建临时表空间池,则拒绝启动。
shell> cd BASEDIR
/ data /#innodb_temp
shell> ls
temp_10.ibt temp_2.ibt temp_4.ibt temp_6.ibt temp_8.ibt
temp_1.ibt temp_3.ibt temp_5.ibt temp_7.ibt temp_9.ibt
在基于语句的复制(SBR)模式中,在从属服务器上创建的临时表驻留在单个会话临时表空间中,该表空间仅在MySQL服务器关闭时被截断。
该
INNODB_SESSION_TEMP_TABLESPACES
表提供有关会话临时表空间的元数据。
该
INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO
表提供有关在
InnoDB
实例
中处于活动状态的用户创建的临时表的元数据
。
全局临时表空间(
ibtmp1
)存储用于对用户创建的临时表所做更改的回滚段。
该
innodb_temp_data_file_path
变量定义全局临时表空间数据文件的相对路径,名称,大小和属性。
如果没有指定值
innodb_temp_data_file_path
,默认行为是创建一个名为一个自动扩展数据文件
ibtmp1
的
innodb_data_home_dir
目录。
初始文件大小略大于12MB。
在正常关闭或中止初始化时删除全局临时表空间,并在每次启动服务器时重新创建。 全局临时表空间在创建时会收到动态生成的空间ID。 如果无法创建全局临时表空间,则拒绝启动。 如果服务器意外停止,则不会删除全局临时表空间。 在这种情况下,数据库管理员可以手动删除全局临时表空间或重新启动MySQL服务器。 重新启动MySQL服务器会自动删除并重新创建全局临时表空间。
全局临时表空间不能驻留在原始设备上。
INFORMATION_SCHEMA.FILES
提供有关全局临时表空间的元数据。
发出类似于此查询的查询以查看全局临时表空间元数据:
MySQL的> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G
默认情况下,全局临时表空间数据文件是自动扩展的,并根据需要增加大小。
要确定全局临时表空间数据文件是否自动扩展,请检查以下
innodb_temp_data_file_path
设置:
MySQL的> SELECT @@innodb_temp_data_file_path;
+ ------------------------------ +
| @@ innodb_temp_data_file_path |
+ ------------------------------ +
| ibtmp1:12M:autoextend |
+ ------------------------------ +
要检查全局临时表空间数据文件的大小,请
INFORMATION_SCHEMA.FILES
使用与此类似的查询来
查询
表:
MySQL的>SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE
AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILES
WHERE TABLESPACE_NAME = 'innodb_temporary'\G
*************************** 1。排******************** ******* FILE_NAME:./ ibtmp1 TABLESPACE_NAME:innodb_temporary ENGINE:InnoDB INITIAL_SIZE:12582912 TotalSizeBytes:12582912 DATA_FREE:6291456 MAXIMUM_SIZE:NULL
TotalSizeBytes
显示全局临时表空间数据文件的当前大小。
有关其他字段值的信息,请参见
第25.11节“INFORMATION_SCHEMA文件表”
。
或者,检查操作系统上的全局临时表空间数据文件大小。
全局临时表空间数据文件位于由
innodb_temp_data_file_path
变量
定义的目录中
。
要回收全局临时表空间数据文件占用的磁盘空间,请重新启动MySQL服务器。
重新启动服务器将根据定义的属性删除并重新创建全局临时表空间数据文件
innodb_temp_data_file_path
。
要限制全局临时表空间数据文件的大小,请配置
innodb_temp_data_file_path
以指定最大文件大小。
例如:
的[mysqld] innodb_temp_data_file_path = ibtmp1:12M:自动扩展:最大:500M
配置
innodb_temp_data_file_path
需要重新启动服务器。
该
CREATE
TABLE ...
DATA DIRECTORY
子句允许
在数据目录之外
创建
每表文件表
空间。
例如,您可以使用该
DATA DIRECTORY
子句在具有特定性能或容量特征的单独存储设备上创建表空间,例如快速
SSD
或高容量
HDD
。
确保您选择的位置。
该
DATA
DIRECTORY
子句不能用于
ALTER
TABLE
以后更改位置。
表空间数据文件在指定目录中创建,该目录位于为表所属的模式命名的子目录中。
以下示例演示如何在数据目录之外创建每个表的文件表空间。
假设
innodb_file_per_table
变量已启用。
MySQL的>USE test;
数据库已更改 MySQL的>CREATE TABLE t1 (c1 INT PRIMARY KEY) DATA DIRECTORY = '
#MySQL在名为的子目录中创建表空间文件 #表示表所属的模式 shell>/remote/directory
';cd /remote/directory/test
shell>ls
t1.ibd
在数据目录之外创建表空间时,请确保已知该目录
InnoDB
。
否则,如果服务器在完全刷新表空间数据文件页面之前意外暂停,则在检索已知目录中的表空间数据文件的恢复前发现阶段未找到表空间时启动失败(请参阅
崩溃恢复期间的表空间发现
)。
要使目录已知,请将其添加到
innodb_directories
参数值。
innodb_directories
是一个只读启动选项,用于定义在启动时扫描表空间数据文件的目录。
配置它需要重新启动服务器。
CREATE
TABLE ...
TABLESPACE
语法也可以与
DATA DIRECTORY
子句
结合使用,
以在数据目录之外创建每表文件表空间。
为此,请指定
innodb_file_per_table
为表空间名称。
MySQL的>CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table
DATA DIRECTORY = '/remote/directory';
innodb_file_per_table
使用此方法时,不需要启用
该
变量。
MySQL最初将表空间数据文件保持打开状态,阻止您卸载设备,但如果服务器繁忙,最终可能会关闭表。 小心不要在MySQL运行时意外卸载外部设备,或在设备断开连接时启动MySQL。 在关联的表空间数据文件丢失时尝试访问表会导致严重错误,需要重新启动服务器。
如果表空间数据文件不在预期路径,则服务器重新启动会发出错误和警告。 在这种情况下,您可以从备份还原表空间数据文件,或删除表以从 数据字典中 删除有关它的 信息 。
在将表空间放在已安装NFS的卷上之前,请查看 使用NFS与MySQL中 列出的潜在问题 。
如果使用LVM快照,文件副本或其他基于文件的机制来备份表空间数据文件,请始终
FLUSH
TABLES ... FOR EXPORT
首先
使用该
语句,以确保
在备份发生之前将
内存中缓冲的所有更改
刷新
到磁盘。
本节介绍如何将
每个表
的
文件表
空间从一个MySQL实例
复制
到另一个MySQL实例,也称为可
传输表空间
功能。
此功能还支持分区
InnoDB
表和单个
InnoDB
表分区和子分区。
有关其他
InnoDB
表复制方法的信息,请参见
第15.6.1.2节“移动或复制InnoDB表”
。
将
InnoDB
每个表文件表
空间
复制
到另一个实例的
原因有很多
:
只有在
innodb_file_per_table
启用
时才能使用表空间复制过程
,这是默认设置。
驻留在共享系统表空间中的表无法停顿。
当表静默时,受影响的表上只允许只读事务。
导入表空间时,页面大小必须与导入实例的页面大小匹配。
ALTER
TABLE ...
DISCARD TABLESPACE
分区
InnoDB
表
ALTER
TABLE ...
DISCARD PARTITION ... TABLESPACE
支持,
InnoDB
表分区
支持
。
DISCARD TABLESPACE
不支持与父子时(主键-外键)关系表空间
foreign_key_checks
设置为
1
。
在丢弃父子表的表空间之前,请设置
foreign_key_checks=0
。
分区
InnoDB
表不支持外键。
ALTER
TABLE ...
IMPORT TABLESPACE
不会对导入的数据强制执行外键约束。
如果表之间存在外键约束,则应在相同(逻辑)时间点导出所有表。
分区
InnoDB
表不支持外键。
ALTER
TABLE ...
IMPORT TABLESPACE
并且
ALTER
TABLE ...
IMPORT PARTITION ... TABLESPACE
不需要
.cfg
元数据文件来导入表空间。
但是,在没有
.cfg
文件
导入时不执行元数据检查
,并发出类似于以下的警告:
消息:InnoDB:IO读取错误:(2,没有这样的文件或目录)错误打开'。\ test \ t.cfg'将尝试导入而不进行模式验证 1排(0.00秒)
.cfg
当没有预期的模式不匹配时,没有文件
导入的能力
可能更方便。
此外,在没有
.cfg
文件的情况下
导入的
功能在崩溃恢复方案中非常有用,在这种情况下无法从
.ibd
文件中
收集元数据
。
如果未
.cfg
使用
任何
文件,则
InnoDB
使用等效的
语句来初始化用于为
列
分配值的内存中自动增量计数器
。
否则,从
元数据文件中
读取当前最大自动增量计数器值
。
有关相关信息,请参阅
InnoDB AUTO_INCREMENT计数器初始化
。
SELECT MAX(ai_col) FROM
table_name
FOR UPDATEAUTO_INCREMENT
.cfg
由于
.cfg
元数据文件限制,在导入分区表的表空间文件时,不会报告分区类型或分区定义差异的模式不匹配。
报告了列差异。
运行
ALTER
TABLE ...
DISCARD PARTITION ... TABLESPACE
和
ALTER
TABLE ...
IMPORT PARTITION ... TABLESPACE
在子分区表上时,允许分区和子分区表名称。
指定分区名称时,该分区的子分区将包含在操作中。
如果两个实例都具有GA(一般可用性)状态,并且导入文件的服务器实例在同一版本系列中处于相同或更高版本级别,则从另一个MySQL服务器实例导入表空间文件。 不支持将表空间文件导入到运行早期版本的MySQL的服务器实例中。
在复制方案中,
innodb_file_per_table
必须
ON
在主服务器和从服务器上都
设置为
。
在Windows上,
InnoDB
内部以小写形式存储数据库,表空间和表名。
为避免在区分大小写的操作系统(如Linux和UNIX)上导入问题,请使用小写名称创建所有数据库,表空间和表。
完成此操作的一种便捷方法是
在创建数据库,表空间或表之前将以
下行添加到
或
文件
的
[mysqld]
部分
:
my.cnf
my.ini
的[mysqld] 的lower_case_table_names = 1
禁止
lower_case_table_names
使用与初始化
服务器时使用的
设置不同的设置启动服务器。
ALTER
TABLE ...
DISCARD TABLESPACE
并且
ALTER
TABLE
...IMPORT TABLESPACE
不支持属于
InnoDB
常规表空间的表。
有关更多信息,请参阅
CREATE TABLESPACE
。
InnoDB
表
的默认行格式
可使用
innodb_default_row_format
配置选项
进行
配置。
如果
源实例上的设置与目标实例上的设置不同,则
尝试导入未显式定义行format(
ROW_FORMAT
)或使用的表
ROW_FORMAT=DEFAULT
可能导致模式不匹配错误
innodb_default_row_format
。
有关相关信息,请参阅
定义表的行格式
。
导出加密表空间时,
除了
元数据文件
外,还会
InnoDB
生成
文件。
在
对目标实例
执行
操作
之前,
必须将
文件与文件和表空间文件
一起复制到
目标实例。
该
文件包含传输密钥和加密的表空间密钥。
在导入时,
使用传输密钥来解密表空间密钥。
有关相关信息,请参见
第15.6.3.9节“InnoDB静态数据加密”
。
.cfp
.cfg
.cfp
.cfg
ALTER TABLE ...
IMPORT TABLESPACE
.cfp
InnoDB
FLUSH
TABLES ... FOR EXPORT
具有FULLTEXT索引的表不受支持。
不刷新全文搜索辅助表。
导入带
FULLTEXT
索引
的表后
,运行
OPTIMIZE TABLE
以重建
FULLTEXT
索引。
或者,
FULLTEXT
在导出操作之前
删除
索引,并在导入目标实例上的表后重新创建它们。
如果要传输使用
InnoDB
表空间加密
进行加密的
表,请
在开始获取其他过程信息之前
参阅
限制和使用说明
。
此过程演示如何将常规
InnoDB
表从正在运行的MySQL服务器实例
复制
到另一个正在运行的实例。
可以使用具有微小调整的相同过程在同一实例上执行完整表还原。
在源实例上,创建一个表(如果不存在):
mysql>USE test;
mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
在目标实例上,创建一个表(如果不存在):
mysql>USE test;
mysql>CREATE TABLE t(c1 INT) ENGINE=InnoDB;
在目标实例上,放弃现有表空间。
(在导入表空间之前,
InnoDB
必须丢弃附加到接收表的表空间。)
MySQL的> ALTER TABLE t DISCARD TABLESPACE;
在源实例上,运行
FLUSH
TABLES ... FOR EXPORT
以停顿表并创建
.cfg
元数据文件:
mysql>USE test;
mysql>FLUSH TABLES t FOR EXPORT;
metadata(
.cfg
)在
InnoDB
数据目录中
创建
。
该
FLUSH
TABLES ... FOR EXPORT
语句确保已将对指定表的更改刷新到磁盘,以便在实例运行时可以生成二进制表副本。
当
FLUSH
TABLES ... FOR EXPORT
运行时,
InnoDB
产生了
.cfg
在同一个数据库的目录表文件。
该
.cfg
文件包含导入表空间文件时用于模式验证的元数据。
将
.ibd
文件和
.cfg
元数据文件从源实例
复制
到目标实例。
例如:
外壳> scp /path/to/datadir
/test/t.{ibd,cfg} destination-server:/path/to/datadir
/test
的
.ibd
文件和
.cfg
文件必须释放共享锁之前如在下一步中所述被复制。
在源实例上,用于
UNLOCK
TABLES
释放通过
FLUSH
TABLES ... FOR EXPORT
以下方式
获取的锁
:
mysql>USE test;
mysql>UNLOCK TABLES;
在目标实例上,导入表空间:
mysql>USE test;
mysql>ALTER TABLE t IMPORT TABLESPACE;
该
ALTER
TABLE ... IMPORT TABLESPACE
功能不会对导入的数据强制执行外键约束。
如果表之间存在外键约束,则应在相同(逻辑)时间点导出所有表。
在这种情况下,您将停止更新表,提交所有事务,获取表上的共享锁,然后执行导出操作。
此过程演示如何将分区
InnoDB
表从正在运行的MySQL服务器实例
复制
到另一个正在运行的实例。
可以使用具有微小调整的相同过程
InnoDB
在同一实例上
执行分区
表
的完全还原
。
在源实例上,创建分区表(如果不存在)。 在以下示例中,将创建一个包含三个分区(p0,p1,p2)的表:
mysql>USE test;
mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
在
目录中,
三个分区中的每个分区
都有一个单独的tablespace(
)文件。
/
datadir
/test.ibd
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
在目标实例上,创建相同的分区表:
mysql>USE test;
mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 3;
在
目录中,
三个分区中的每个分区
都有一个单独的tablespace(
)文件。
/
datadir
/test.ibd
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
在目标实例上,丢弃分区表的表空间。 (在可以在目标实例上导入表空间之前,必须丢弃附加到接收表的表空间。)
MySQL的> ALTER TABLE t1 DISCARD TABLESPACE;
.ibd
组成分区表的表空间
的三个
文件将从
目录
中丢弃
。
/
datadir
/test
在源实例上,运行
FLUSH
TABLES ... FOR EXPORT
以停顿分区表并创建
.cfg
元数据文件:
mysql>USE test;
mysql>FLUSH TABLES t1 FOR EXPORT;
在源实例
的
目录
中创建
Metadata(
.cfg
)文件,每个tablespace(
.ibd
)文件
一个
文件
:
/
datadir
/test
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd
t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg
FLUSH
TABLES ... FOR EXPORT
语句确保已将对指定表的更改刷新到磁盘,以便在实例运行时进行二进制表复制。
当
FLUSH
TABLES ... FOR EXPORT
运行时,
InnoDB
产生
.cfg
在同一数据库的目录表中的表的表空间文件元数据文件。
这些
.cfg
文件包含导入表空间文件时用于模式验证的元数据。
FLUSH
TABLES ... FOR EXPORT
只能在表上运行,而不能在单个表分区上运行。
将
.ibd
和
.cfg
实例数据库目录中
的
和
文件
复制
到目标实例数据库目录。
例如:
壳> SCP /path/to/datadir
/test/t1*.{ibd,cfg} destination-server:/path/to/datadir
/test
的
.ibd
和
.cfg
文件必须释放共享锁之前如在下一步中所述被复制。
在源实例上,用于
UNLOCK
TABLES
释放通过
FLUSH
TABLES ... FOR EXPORT
以下方式
获取的锁
:
mysql>USE test;
mysql>UNLOCK TABLES;
在目标实例上,导入分区表的表空间:
mysql>USE test;
mysql>ALTER TABLE t1 IMPORT TABLESPACE;
此过程演示如何将
InnoDB
表分区从正在运行的MySQL服务器实例
复制
到另一个正在运行的实例。
可以使用具有微小调整的相同过程
InnoDB
在同一实例上
执行
表分区
的还原
。
在以下示例中,将在源实例上创建具有四个分区(p0,p1,p2,p3)的分区表。
其中两个分区(p2和p3)被复制到目标实例。
在源实例上,创建分区表(如果不存在)。 在以下示例中,将创建一个包含四个分区(p0,p1,p2,p3)的表:
mysql>USE test;
mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
在
目录中,
四个分区中的每个分区
都有一个单独的tablespace(
)文件。
/
datadir
/test.ibd
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
在目标实例上,创建相同的分区表:
mysql>USE test;
mysql>CREATE TABLE t1 (i int) ENGINE = InnoDB PARTITION BY KEY (i) PARTITIONS 4;
在
目录中,
四个分区中的每个分区
都有一个单独的tablespace(
)文件。
/
datadir
/test.ibd
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
在目标实例上,丢弃计划从源实例导入的表空间分区。 (可以在目标实例上导入表空间分区之前,必须丢弃附加到接收表的相应分区。)
MySQL的> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;
.ibd
从
目标实例上的目录
中删除两个丢弃的分区
的
文件
,留下以下文件:
/
datadir
/test
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd
当
ALTER
TABLE ... DISCARD PARTITION ... TABLESPACE
上subpartitioned表上运行,无论分区和子分区表名是允许的。
指定分区名称时,该分区的子分区将包含在操作中。
在源实例上,运行
FLUSH
TABLES ... FOR EXPORT
以停顿分区表并创建
.cfg
元数据文件。
mysql>USE test;
mysql>FLUSH TABLES t1 FOR EXPORT;
元数据文件(
.cfg
文件)
在源实例
的
目录
中创建
。
有一个
为每个表空间(文件
)文件。
/
datadir
/test.cfg
.ibd
MySQL的> \! ls /path/to/datadir
/test/
t1#P#p0.ibd t1#P#p1.ibd t1#P#p2.ibd t1#P#p3.ibd
t1#P#p0.cfg t1#P#p1.cfg t1#P#p2.cfg t1#P#p3.cfg
FLUSH
TABLES ... FOR EXPORT
语句确保已将对指定表的更改刷新到磁盘,以便在实例运行时进行二进制表复制。
当
FLUSH
TABLES ... FOR EXPORT
运行时,
InnoDB
产生
.cfg
在同一数据库的目录表中的表的表空间文件元数据文件。
这些
.cfg
文件包含导入表空间文件时用于模式验证的元数据。
FLUSH
TABLES ... FOR EXPORT
只能在表上运行,而不能在单个表分区上运行。
将
.ibd
和
.cfg
实例数据库目录中
的
和
文件
复制
到目标实例数据库目录。
在此示例中,仅将
分区2(p2)和分区3(p3)
的
.ibd
和
.cfg
文件复制到
data
目标实例上的目录。
分区0(p0)和分区1(p1)保留在源实例上。
外壳> scp t1#P#p2.ibd t1#P#p2.cfg t1#P#p3.ibd t1#P#p3.cfg destination-server:/path/to/datadir
/test
的
.ibd
文件和
.cfg
文件必须释放共享锁之前如在下一步中所述被复制。
在源实例上,用于
UNLOCK
TABLES
释放通过
FLUSH
TABLES ... FOR EXPORT
以下方式
获取的锁
:
mysql>USE test;
mysql>UNLOCK TABLES;
在目标实例上,导入表空间分区(p2和p3):
mysql>USE test;
mysql>ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
当
ALTER
TABLE ... IMPORT PARTITION ... TABLESPACE
上subpartitioned表上运行,无论分区和子分区表名是允许的。
指定分区名称时,该分区的子分区将包含在操作中。
以下信息描述了常规
InnoDB
表
的可传输表空间复制过程的内部和错误日志消息传递
。
何时
ALTER
TABLE
... DISCARD TABLESPACE
在目标实例上运行:
该表被锁定在X模式下。
表空间与表分离。
何时
FLUSH
TABLES ... FOR EXPORT
在源实例上运行:
刷新导出的表在共享模式下被锁定。
清除协调器线程已停止。
脏页面与磁盘同步。
表元数据被写入二进制
.cfg
文件。
此操作的预期错误日志消息:
2013-09-24T13:10:19.903526Z 2 [注意] InnoDB:与“test”同步到磁盘。“t”'开始了。 2013-09-24T13:10:19.903586Z 2 [注意] InnoDB:停止清除 2013-09-24T13:10:19.903725Z 2 [注意] InnoDB:将表格元数据写入'./test/t.cfg' 2013-09-24T13:10:19.904014Z 2 [注意] InnoDB:表'“test”。“t”'刷新到磁盘
何时
UNLOCK
TABLES
在源实例上运行:
二进制.cfg文件已删除。
将导入要导入的表上的共享锁,并重新启动清除协调程序线程。
此操作的预期错误日志消息:
2013-09-24T13:10:21.181104Z 2 [注意] InnoDB:删除元数据文件'./test/t.cfg' 2013-09-24T13:10:21.181180Z 2 [注意] InnoDB:恢复清除
在
ALTER
TABLE
... IMPORT TABLESPACE
目标实例上运行时,导入算法会为要导入的每个表空间执行以下操作:
检查每个表空间页面是否损坏。
每页上的空间ID和日志序列号(LSN)都会更新
验证标志并更新标题页的LSN。
Btree页面已更新。
页面状态设置为脏,以便将其写入磁盘。
此操作的预期错误日志消息:
2013-07-18 15:15:01 34960 [注意] InnoDB:导入从主机'ubuntu'导出的表'test / t'的表空间 2013-07-18 15:15:01 34960 [注意] InnoDB:第一阶段 - 更新所有页面 2013-07-18 15:15:01 34960 [注意] InnoDB:同步到磁盘 2013-07-18 15:15:01 34960 [注意] InnoDB:同步到磁盘 - 完成! 2013-07-18 15:15:01 34960 [注意] InnoDB:第三阶段 - 刷新磁盘更改 2013-07-18 15:15:01 34960 [注意] InnoDB:第四阶段 - 冲洗完成
您可能还会收到一个警告,表示已丢弃表空间(如果您丢弃了目标表的表空间),并且收到一条消息,指出由于缺少
.ibd
文件
而无法计算统计信息
:
2013-07-18 15:14:38 34960 [警告] InnoDB:表“test”。“t”表空间被设置为丢弃。 2013-07-18 15:14:38 7f34d9a37700 InnoDB:无法计算表“test”的统计数据。“t” 因为缺少.ibd文件。如需帮助,请参阅 http://dev.mysql.com/doc/refman/8.0/en/innodb-troubleshooting.html
该
innodb_directories
选项定义了在启动时扫描表空间文件的目录,支持在服务器脱机时将表空间文件移动或恢复到新位置。
在启动期间,使用发现的表空间文件而不是数据字典中引用的那些文件,并更新数据字典以引用重定位的文件。
如果扫描发现重复的表空间文件,则启动失败,并显示错误,指示为同一表空间ID找到了多个文件。
由定义的目录
innodb_data_home_dir
,
innodb_undo_directory
和
datadir
配置选项自动附加到
innodb_directories
参数值。
无论是否
innodb_directories
明确指定选项,
都会在启动时扫描这些目录
。
隐式添加这些目录允许移动系统表空间文件,数据目录或撤消表空间文件,而无需配置
innodb_directories
设置。
但是,目录更改时必须更新设置。
例如,重定位数据目录后,必须