04 深入专题:InnoDB 存储引擎
这一篇聚焦 InnoDB 存储引擎内部机制:B+ 树页结构、Change Buffer、Double Write、自适应哈希、Redo/Undo、Buffer Pool 与 LRU 策略等底层原理。内容整理自爱可生开源社区《大智小技》系列(2019/2020 两册)技术文章精选。
InnoDB 表空间加密如何配置与创建加密表?
用 keyring_file 插件:my.cnf 设 early-plugin-load=“keyring_file.so”、keyring_file_data=路径、innodb_file_per_table=1,建好密钥环目录并设权限;启动时自动生成首个主密钥。建表加 ENCRYPTION=‘Y’,如 CREATE TABLE test_1(…) ENCRYPTION=‘Y’;ALTER TABLE … ENCRYPTION=‘N’/‘Y’ 可切换。仅支持独立表空间,企业版另有 keyring_encrypted_file/okv/aws。
InnoDB 表空间加密有哪些限制和注意事项?
限制:1) AES 唯一算法,ECB 加密 key、CBC 加密数据;2) ENCRYPTION 用 COPY 而非 INPLACE;3) 仅独立表空间,不支持通用/系统表空间;4) 不能移到不支持加密的表空间;5) 只加密表空间数据,不加密 redo/undo/binlog;6) 不允许改已加密表的存储引擎。注意:主密钥丢失则数据不可恢复,必须备份 keyring;keyring 勿与表空间同目录;主从均需配置加密。
InnoDB 表空间加密(Transparent Encryption)的架构与密钥层次是怎样的?
5.7.11 起 InnoDB 支持独立表空间静态数据加密(透明加密),数据页写入加密、读出解密,页大小不变。采用两层密钥:master encryption key 加密 tablespace key 并存入表空间头部;tablespace key 加密表空间文件。访问时先用 master key 解密出明文 tablespace key,再用其解密数据。AES 算法,ECB 模式加密 tablespace key、CBC 模式加密数据文件。
MySQL 存储图片等大对象(BLOB/TEXT)时,三种存储方式的磁盘占用对比?
建三表分别用 LONGBLOB、LONGTEXT、VARCHAR(存路径) 各插 100 张 5M 图片:tt_image2(LONGTEXT).ibd 1.1G 最大,tt_image1(LONGBLOB).ibd 544M,tt_image3(路径) 仅 112K。可见存路径最省空间。取出时路径表直接 SELECT,LONGBLOB 用 SELECT … INTO DUMPFILE 导出,LONGTEXT 需 UNHEX。结论:不推荐在 MySQL 存大文件,应用文件路径。
在 MySQL 中存储大对象(图片)有哪些使用与运维上的缺点?
- 占用磁盘空间巨大(100张5M图,LONGTEXT 表 1.1G),带来备份、写入、读取各方面性能与功能问题;2) 使用不易,需存储过程+INTO DUMPFILE/UNHEX 才能导出;3) 超出记录数视角,空间大小才是瓶颈。文中总结三点:占用空间大、使用不易,仍推荐用文件路径代替文件内容存放。
如何判断 MySQL 表是否存在碎片,碎片产生的原因是什么?
用 SHOW TABLE STATUS FROM db\G 查看 Data_free 字段,不为 0 即存在碎片。成因:1) 频繁 DELETE 留空白区,新插入难完全复用;2) UPDATE 变长字段(如 varchar)由长改短,原长度无法有效利用。碎片导致空间不连续、磁盘 I/O 变为离散随机读写,加重负担。MyISAM 表用 optimize table;InnoDB 用 ALTER TABLE … ENGINE=InnoDB 重建或导入导出。
如何导出导入 InnoDB 加密表(跨实例迁移)?
引入 transfer_key:源库 FLUSH TABLES test_1 FOR EXPORT 生成 .cfg 和 .cfp(含用 transfer_key 加密的 tablespace key,明文保存);目标库先建同名同结构加密表、ALTER TABLE … DISCARD TABLESPACE,scp 拷贝 .ibd/.cfg/.cfp 并改权限,源库 UNLOCK TABLES,目标库 ALTER TABLE … IMPORT TABLESPACE 完成(导入后 .cfg 删除)。.cfp 用于传输密钥。
如何更新(rotate)InnoDB 的主加密密钥 master encryption key?
执行 ALTER INSTANCE ROTATE INNODB MASTER KEY; 该操作原子、实例级:仅改变 master key 并重新加密所有 tablespace key 写入各表空间头部(tablespace key 明文不变,故不重加密数据文件)。keyring 文件大小会从 155 字节变为 283 字节。成功后不影响已有加密表的正常读写,建议在怀疑密钥泄露或定期轮换时执行。
如何查看 InnoDB 中哪些表被加密了?
通过 INFORMATION_SCHEMA.TABLES 的 CREATE_OPTIONS 字段判断:SELECT TABLE_SCHEMA,TABLE_NAME,CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES WHERE CREATE_OPTIONS LIKE ‘%ENCRYPTION%’; 加密表会显示 ENCRYPTION=‘Y’;反查未加密表可用 NOT IN 子查询排除已加密的。此外 keyring 文件需妥善保管,移除后已建加密表仍可读写(重启/轮换前)。
清理 MySQL 表碎片有哪些方法,性能提升效果如何?
MyISAM:OPTIMIZE TABLE 整理数据文件并重排索引。InnoDB:ALTER TABLE tablename ENGINE=InnoDB(重建表、重新组织数据),或做一次数据导入导出。文中生产库对比:清理前 SELECT COUNT(*) FROM test.twitter_11 耗时 7.37s,清理后 1.28s,明显提速且节省空间。建议在低峰期操作,注意会锁表。
用 innobackupex 备份恢复 InnoDB 加密表空间需要注意什么?
innobackupex 仅支持 keyring_file、keyring_vault 插件加密表空间的备份;不会复制密钥环文件,须手动复制 keyring 到 –keyring-file-data 指定路径,备份前后密钥环不同则还原用旧的。示例:全备加 –keyring-file-data=/path/keyring,apply-log 同样指定,copy-back 后改权限再启动。mysqlbackup 4.1.1+ 支持 5.7 加密备份。
Adaptive Hash Index 建立需要经过哪三个关卡?
关卡1:某索引树被使用足够多次(只为频繁使用的索引建 AHI,避免太多);关卡2:该索引树上某检索条件常被使用,用 hash info(匹配列数、首不匹配列匹配字节数、是否从左往右)选出常用条件;关卡3:该索引树上某数据页常被使用(只为常访问的部分数据建)。三关通过后才为数据页每行按 hash info 建 AHI 项(如(1,2)哈希→P3)。
Adaptive Hash Index(AHI)是为解决什么问题而设计的?
随单表数据增大,B+树层数增多,检索数据页需逐层定位,时间成本上升。AHI 是“检索条件→数据页”的哈希缓存,跳过逐层定位直接命中数据页。“自适应”指哈希表不能太大(维护成本超收益)也不能太小(命中率低无收益),只为频繁使用的索引和常访问的数据页建立缓存,达到“不大不小刚刚好”。
MySQL 8.0 中 Adaptive Hash Index 有哪些运维要点?
- innodb_adaptive_hash_index_parts:将 AHI 分多个区,各用独立锁减少锁竞争;2) SHOW ENGINE INNODB STATUS 可看各分区使用率与命中率,命中过低可分析访问模式或关闭 AHI 减维护成本;3) 低版本存在 AHI 相关 bug 影响业务,新版本已修复可放心用。理解建立原理有助于判断业务是否该命中 AHI。