InnoDB 的历史

年份 事件 备注
1995 由 Heikki Tuuri 创建 Innobase Oy 公司,并开发 InnoDB 存储引擎 Innobase 开始做的是数据库,希望卖掉该公司
1996 MySQL 1.0 发布
2000 MySQL 3.23 版本发布
2001 InnoDB 存储引擎集成到 MySQL 数据库 作为插件的方式集成
2006 Innobase 被 Oracle 公司收购(InnoDB 作为开源产品,性能和功能很强大) InnoDB 在被收购后的,MySQL 中的 InnoDB 版本没有改变
2010 MySQL 5.5 版本 InnoDB 存储引擎称为默认存储引擎 MySQL 被 Sun 收购,Oracle 被 Oracle 收购,使得 MySQL 和 InnoDB 重新在一起配合开发
至今 其他存储引擎已经不再得到 Oracle 官方的后续开发

InnoDB 的特点

  • Fully ACID:InnoDB 默认的 Repeat Read 隔离级别就支持
  • Row-level Locking:支持行锁
  • Multi-version concurrency control(MVCC):支持多版本并发控制
  • Foreign key support:支持外键
  • Automatic deadlock detection:死锁自动检测
  • High performance、High scalability、High availability:高性能,高扩展,高可用

InnoDB 存储引擎的文件

概述

InnoDB 的文件主要分为两个部分,一个是表空间文件,一个是重做日志文件。

表空间文件

  • 独立表空间文件
  • 全局表空间文件
  • Undo 表空间文件(from MySQL 5.6)

重做日志文件

  • 物理逻辑日志
  • 没有 Oracle 的归档重做日志

InnoDB 表空间

表空间的概念

  • 表空间是一个逻辑存储的概念
  • 表空间可以由多个文件组成
  • 支持裸设备(可以直接使用 O_DIRECT 方式绕过缓存,直接写入磁盘)

表空间的分类

系统表空间 (最早只有系统表空间)

  • 存储元数据信息
  • 存储 Change Buffer 信息
  • 存储 Undo 信息
  • 一开始所有的表和索引的信息都是存储在系统表空间中,随后 InnoDB 对其做了改进,可以使用独立的表空间

独立表空间

  • innodb-file-per-table=1(开启支持每个表一个独立的表空间)
  • 每张用户表对应一个独立的 ibd 文件
  • 分区表可以对应多个 ibd 文件

Undo 表空间

  • MySQL 5.6 版本支持独立的 Undo 表空间
  • innodb_undo_tablespaces=3,创建3个 Undo 表空间

    1. shell> ll undo*
    2. -rw-r-----. 1 mysql mysql 7340032 Jan 3 17:21 undo001
    3. -rw-r-----. 1 mysql mysql 7340032 Jan 3 17:40 undo002
    4. -rw-r-----. 1 mysql mysql 7340032 Jan 3 17:21 undo003

    临时表空间

  • MySQL 5.7 增加了临时表空间(ibtmp1)

  • innodb_temp_data_file_path

查看 MySQL 的 datadir 目录。

  1. shell> ll ib* # MySQL的datadir目录
  2. -rw-r-----. 1 mysql mysql 22913 Dec 27 23:56 ib_buffer_pool
  3. -rw-r-----. 1 mysql mysql 12582912 Jan 3 15:27 ibdata1 # 系统表空间,默认所有信息存在这里
  4. -rw-r-----. 1 mysql mysql 134217728 Jan 3 15:27 ib_logfile0
  5. -rw-r-----. 1 mysql mysql 134217728 Jan 3 15:27 ib_logfile1
  6. -rw-r-----. 1 mysql mysql 12582912 Jan 3 15:27 ibtmp1 # 零时表空间
  7. shell> cd burn_test # 在MySQL的datadir目录下,burn_test是自定义数据库,根据配置,默认为innodb的表
  8. shell> ll test_1*
  9. -rw-r-----. 1 mysql mysql 8554 Dec 3 20:14 test_1.frm # test_1表的表结构文件
  10. # mysqlfrm --diagnostic test_1.frm可查看表结构
  11. -rw-r-----. 1 mysql mysql 49152 Dec 3 20:14 test_1.ibd # ibd就是test_1这张表对应的innodb文件
  12. # ibd中包含了索引和数据
  • 同一个表空间(ibdata1)存储和独立表空间存储就性能上而言没有区别;
  • 当需要删除表(drop table)时,独立的表空间存储可以直接删除文件,而 ibdata1 存储也只是把该部分表空间标记为可用,所以从速度上看很难说哪个更快;但是删除文件后,ibdata1 占用的空间不会释放;
  • 分区表,每个分区会产生独立的 ibd 文件 ;
  • 独立的表空间,一个表对应一个 ibd 文件,给人的感觉更加直观;
  • 单个 ibd 文件直接拷贝到新的数据库中无法直接恢复:
    • 原因一:元数据信息还是在 ibdata1 中;
    • 原因二:部分索引文件存在于 Change Buffer 中,目前还是存放于 ibdata1文件中;
      1. select * from information_schema.innodb_sys_tablespaces\G -- 查看表空间的元数据信息

      InnoDB 重做日志

innodb_log_file_size

  • 该文件设置的尽可能的大,模板中给出的大小是 4G
  • 设置太小可能会导致脏页刷新时夯住

General 表空间

General 表空间是 InnoDB 使用 CREATE TABLESPACE 语法创建的共享表空间。

官方文档:https://dev.mysql.com/doc/refman/5.7/en/general-tablespaces.html

假如,新建一张表并让该表的存储路径不是默认的路径 datadir/dbname,而是指定存储的位置,应该如何处理?

方法一:

  1. shell> mkdir /GeneralTest
  2. shell> chown mysql.mysql /GeneralTest
  3. mysql> create table test_ger1 (a int) data directory='/GeneralTest';
  4. Query OK, 0 rows affected (0.15 sec)
  5. shell> cd /GeneralTest
  6. shell> tree
  7. .
  8. └── burn_test # dbname
  9. └── test_ger1.ibd # 表空间文件
  10. 1 directory, 1 file
  11. shell> ll test_ger1* # 在datadir 的 burn_test 目录下
  12. -rw-r-----. 1 mysql mysql 8554 Jan 3 16:41 test_ger1.frm
  13. -rw-r-----. 1 mysql mysql 36 Jan 3 16:41 test_ger1.isl # 这是链接文件,链接到上面的ibd文件
  14. shell> cat test_ger1.isl # 一个文本文件,内容就是idb文件的路径
  15. /GeneralTest/burn_test/test_ger1.ibd

方法二:

  1. -- 使用`通用表空间`
  2. -- 1: 创建一个通用表空间
  3. mysql> create tablespace ger_space add datafile '/GeneralTest/ger_space.ibd' file_block_size=8192;
  4. Query OK, 0 rows affected (0.07 sec)
  5. -- datafile 指定存储路径后,在datadir下会产生一个isl文件,该文件的内容为General spaceibd文件的路径
  6. -- 如果datafile不指定路径,则ibd文件默认存储在datadir目录下,且不需要isl文件了
  7. mysql> create tablespace ger2_space add datafile 'ger2_space.ibd' file_block_size=8192;
  8. Query OK, 0 rows affected (0.06 sec)
  9. shell> ll ger*
  10. -rw-r-----. 1 mysql mysql 32768 Jan 3 16:51 ger2_space.ibd # 未指定路径,存放于datadir目录
  11. -rw-r-----. 1 mysql mysql 26 Jan 3 16:50 ger_space.isl # 指定了其他路径,存在isl链接文件
  12. shell> cat ger_space.isl
  13. /GeneralTest/ger_space.ibd # ibd文件真实存在的路径
  14. mysql> select * from information_schema.innodb_sys_tablespaces where name='ger_space'\G
  15. *************************** 1. row ***************************
  16. SPACE: 96
  17. NAME: ger_space
  18. FLAG: 2304
  19. FILE_FORMAT: Any
  20. ROW_FORMAT: Any
  21. PAGE_SIZE: 8192 -- page_size8k
  22. ZIP_PAGE_SIZE: 0
  23. SPACE_TYPE: General -- General类型
  24. FS_BLOCK_SIZE: 0
  25. FILE_SIZE: 18446744073709551615
  26. ALLOCATED_SIZE: 2
  27. COMPRESSION: None
  28. 1 row in set (0.00 sec)
  29. -- 2: 创建表
  30. mysql> create table test_ger2 (a int) tablespace=ger_space;
  31. Query OK, 0 rows affected (0.11 sec)
  32. shell> ll test_ger* # 在datadir 的 burn_test 目录下
  33. -rw-r-----. 1 mysql mysql 8554 Jan 3 16:41 test_ger1.frm
  34. -rw-r-----. 1 mysql mysql 36 Jan 3 16:41 test_ger1.isl
  35. -rw-r-----. 1 mysql mysql 8554 Jan 3 17:09 test_ger2.frm # 仅有一个frm文件
  36. shell> ll /GeneralTest/
  37. total 52
  38. drwxr-x---. 2 mysql mysql 4096 Jan 3 16:41 burn_test
  39. -rw-r-----. 1 mysql mysql 49152 Jan 3 17:09 ger_space.ibd # test_ger2的ibd文件其实存储在ger_space.ibd的通用表空间中
  40. mysql> create table test_ger3 (a int) tablespace=ger_space; -- test_ger3 也存放在ger_space.ibd
  41. Query OK, 0 rows affected (0.09 sec)
  42. mysql> create tablespace ger3_space add datafile '/GeneralTest/ger3_space.ibd' file_block_size=4096; -- 创建4K大小的General Space也是可以的
  43. Query OK, 0 rows affected (0.06 sec)
  44. -- 但是注意,如果设置了innodb_page_size,且大小不是file_block_size,那么在创建表的时候会报错
  45. -- 这里的 file_block_size 就是 page_size
  46. mysql> create table test_ger (a int) tablespace=ger3_space;
  47. ERROR 1478 (HY000): InnoDB: Tablespace `ger3_space` uses block size 4096 and cannot contain a table with physical page size 8192
  48. -- 既然无法创建表,那应该在创建general space时就应该报错
  49. -- 后续涉及压缩表时可以使用

通过使用 General Space,一个表空间可以对应多张表,当对表进行 alter 等操作时,还是和原来一样,无需额外语法指定表空间位置,可以简单的理解为把多个表的 ibd 文件合并在一起了。

作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/nkflkn 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。