• 欢迎访问DBA的辛酸事儿,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站
  • 欢迎大家关注博主公众号:DBA的辛酸事儿
  • 博文中若有错误的地方,请大家指正,大家的指正是我前进的动力

MySQL InnoDB历史发展

MySQL SEian.G 2年前 (2019-01-23) 829次浏览 已收录 0个评论
文章目录[隐藏]

一、InnoDB存储引擎

InnoDB是事务安全的MySQL存储引擎,设计上采用了类似于Oracle数据库的架构。通常来说,InnoDB存储引擎时OLTP应用中核心表的首选存储引擎。同样,也正是因为InnoDB的存在,才使MySQL数据库变得更有魅力。目前InnoDB属于MySQL默认存储引擎,并且在MySQL 8.0开始,包括元数据表也都是使用InnoDB存储引擎,之前是一直使用MyISAM存储引擎

InnoDB存储引擎的创始人Heikki Tuuri,1964年出生于芬兰赫尔辛基,与著名的Linux创始人Linus同时芬兰赫尔辛基大学校友,同时MySQL创始人Monty也是芬兰人,很传奇。他在1995年成立Innobase Oy公司并担任CEO。InnoDB最初就由Innobase Oy公司开发,后来被包括在MySQL所有的二进制发行版本中,也是MySQL 5.5.8开始默认的存储引擎。该存储引擎是一个支持ACID事务,行锁设计,支持MVCC功能,提供类似于Oracle风格的一致性非锁定读,支持外键,被设计用来最有效地利用内存和CPU。并且实现了SQL标准的4种隔离级别,其默认级别是REPEATABLE READ。并通过一种被称为netxt-key locking的策略来避免幻读。

其实从时间点上来看,InnoDB存储引擎比MySQL(1996年发布1.0版本)出现的还要早一些,起初InnoDB本身就是作为一个独立数据库而开发的,所以它很多功能是比较完整的。后来在2000年MySQL发布了2.0版本,其默认存储引擎就是ISAM(MyISAM的前身,在MySQL 3.23版本被MyISAM替换掉);这期间Innobase Oy公司其实是想把InnoDB给卖掉的,但是由于没人买就一直搁置着。由于MySQL发布2.0后在当时影响还是挺大的,并且由于MySQL是一个插件式数据库,就引起了Innobase Oy公司的注意,后来InnoDB创始人就找MySQL谈,希望MySQL把InnoDB当做一个存储引擎合并到MySQL中,很快双方达成协议,2001年InnoDB就被当做第三方存储引擎集成到MySQL数据库中去了。虽然集成到MySQL了,但是当时MySQL还是主推自家的MyISAM存储引擎,一个不支持事务,表级锁的存储引擎;所以当时如果你创建表时不指定InnoDB为表存储引擎时,默认就是使用MyISAM。好在MySQL 5.5.8版本开始就把InnoDB作为默认存储,所以用户就不需要创建表时还指定InnoDB成表存储引擎,为什么不需要呢?这主要是因为Oracle公司再2006年做了一件前瞻性的决定。

在2006年,Oracle公司收购了Innobase Oy公司,拥有InnoDB存储引擎。据说主要是因为在一次数据库大会上,InnoDB展示了一个表压缩功能,这在当时是很了不起的技术;一个开源的,支持事务、行锁、压缩、MVCC功能的存储引擎真正让Oracle公司感受到了威胁。这也导致了MySQL在很长一段时间内(2006-2010)InnoDB的版本没有任何发展,这几年MySQL也过的不是很好。最终在2008年被SUN公司收购,最后SUN被Oracle收购,自然MySQL也就到了Oracle手里。现在Oracle拥有MySQL数据库及InnoDB存储引擎,从Oracle收购MySQL,推出5.6、5.7、8.0几个大版本,做了大量的优化和功能,并且在8.0大量重构了InnoDB存储引擎,性能大幅度提升。可以说目前能大量重构InnoDB存储引擎的人估计也有Oracle官方团队可以了,包括InnoDB创始人目前也在Oracle公司,如果不出现MySQL被闭源的情况,那么Oracle官方MySQL可以说是前途一片大好。相比MariaDB及Percona来说,由于拥有InnoDB和可重构能力,只要Oracle肯去发展MySQL,那么生产使用基本可以不用考虑其他版本MySQL了。MariaDB就是MySQL被Oracle收购后,其创始人Monty fork MySQL又做出来的一个分支,但其还是使用InnoDB存储引擎;除非MariaDB能够有一款跟InnoDB相匹敌的存储引擎,可能会有意想不到的发展,不然就只能在MySQL层做一些复制及优化器的工作了。另外,目前在InnoDB存储引擎的开发团队中,有来自中国科技大学的Calvin Sun,直到现在这个开发团队中有好几位中国人了。

InnoDB存储引擎已经跟随着MySQL进入到了很多大型网站中使用,如Yahoo、Facebook、淘宝等。从MySQL的官方手册还能得知,著名的Internet新闻站点slashdot.org运行在InnoDB上。还有一些其它站点在InnoDB上处理平均每秒800次插入/更新的操作。这些都证明了InnoDB是一个高性能、高可用、高可扩展的存储引擎。

二、InnoDB体系架构

了解完MySQL的体系结构后,现在再看看InnoDB存储引擎的体系架构。下图简单显示了InnoDB的存储引擎体系结构,InnoDB有多个内存块,你可以认为这些内存块组成了一个大的内存池。

Innodb内存对象
InnoDB存储引擎内存有多个内存块组成,分别是缓冲池、重做日志缓冲池以及额外的内存池。分别由变量innodb_buffer_pool_size、innodb_log_buffer_size、innodb_additional_mem_pool_size的大小决定(调优的参数)。你可以认为这些内存块组成了一个大的内存池,负责如下工作:

1. 维护所有进程/线程需要访问的多个内部数据结构。

2. 缓存磁盘上的数据,方便快速地读取,并且在对磁盘文件的数据进行修改之前在这里缓存。

3. 重做日志(redo log)缓冲,等等。

其中缓冲池是占最大块内存的部分,InnoDB将表的索引和数据进行缓存。缓冲池允许从内存直接处理频繁使用的数据,这加快了处理速度。在专用数据库服务器上,通常将多达80%的物理内存分配给InnoDB缓冲池。因为InnoDB的存储引擎的工作方式总是将数据库文件按页读取到缓冲池,每个页16k默认(innodb_page_size=16k),在MySQL 5.7中增加了32KB和64KB页面大小的支持,之前版本是不允许大于16k的;但你只能在初始化MySQL实例之前进行配置,一旦设置了一个实例的页面大小,就不能改变它,具体看innodb_page_size参数。然后按最近最少使用(LRU)算法来保留在缓冲池中的缓存数据。如果数据库文件需要修改,总是首先修改在缓存池中的页(发生修改后,该也即为脏也),然后再按照一定的频率将缓冲池的脏也刷新到文件中。可以通过show engine innodb status来查看innodb_buffer_pool的具体使用情况(默认是8个缓冲池实例),如下:

root@localhost [(none)]>show engine innodb status\G;
*************************** 1. row ***************************
  Type: InnoDB
  Name: 
Status: 
=====================================
2019-01-23 22:53:02 0x7f23dc195700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 27 seconds
........
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 394940
Buffer pool size   8191
Free buffers       1024
Database pages     7166
Old database pages 2625
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 13591, not young 763374
0.00 youngs/s, 0.00 non-youngs/s
Pages read 26265, created 98, written 343
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 7166, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
.......

在Buffer pool size中可以看到内存池的使用情况,Buffer pool size表明了一共有多少个缓冲帧(buffer frame),每个缓冲帧为16K,所以这里一共分配了8191*16/1024=128M 内存的缓冲池。Free buffers表示当前空闲的缓冲帧,Database pages表示已经使用的缓冲帧,Old database pages表示存放不经常修改的数据页(一般占用内存的1/3),Modified db pages表示脏页的数量,这些数据能分析当前数据库的压力值。

根据上图具体来看:

缓冲池(buffer pool):缓存的数据类型有索引页(index pages)、数据页(data pages)、undo页(undo pages)、插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB存储的锁信息(lock info)、数据字典信息(data dictionary)等。

日志缓冲(log buffer):将重做日志(事务日志)信息先放入这个缓冲区,然后按一定频率将其刷新到重做日志文件。该值一般不需要设置为很大,默认情况下每一秒钟就会将重做日志缓冲刷新到日志文件,因为我们只需要保证每秒产生的事务量在这个缓冲大小之内即可。

额外的内存(additional mem pool):对于管理员来说也是十分重要的,在InnoDB中,对内存的管理是通过一种称为堆(heap)内存的方式进行。在对一些数据结构本身分配内存时,需要从额外的内存池中申请,当该区域的内存不够时,会从缓冲池中申请。Innodb实例会申请缓冲池的空间,但是每个缓冲池中的帧缓冲还有对应的缓冲控制对象,而且这些对象记录了诸如LRU、锁、等待等方面的信息,而这个对象的内存需要从额外内存池中申请。因此当你申请了很大的InnoDB缓冲池时,这个值也应该相应增加。

InnoDB后台线程
后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据。此外,将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常情况下InnoDB能恢复到正常运行的状态。

默认情况下,InnoDB存储引擎的后台线程有7个:4个IO thread(insert,log,read,write),1个master thread,1个锁监控线程,1个错误监控线程。其中master thread线程几乎完成了InnoDB存储引擎所有的功能。(后面会详细介绍master thread)

可以使用show engine innodb status查看InnoDB的状态信息,大概包括事务信息、缓冲池信息、行操作信息以及线程信息等。如下摘取了线程信息:

root@localhost [(none)]>show engine innodb status\G;
*************************** 1. row ***************************
  Type: InnoDB
  Name: 
Status: 
=====================================
2019-01-23 22:53:02 0x7f23dc195700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 27 seconds
........
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
26336 OS file reads, 542 OS file writes, 250 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
.......

可以看到其中4个IO线程分别是上图中的insert buffer thread、log thread、read thread、write thread。而read thread and write thread线程是由这两个变量innodb_read_io_threads和innodb_write_io_threads来控制,默认各自开启4个线程。然后加起来也就出现上面我们看到的10个线程了。

InnoDB存储引擎的主要工作都是在一个单独的后台线程master thread中完成的,master thread的优先级也最高。

三、InnoDB关闭与启动

InnoDB存储引擎现在是MySQL数据库的默认存储引擎,所以InnoDB存储引擎的启动和关闭更准确地是指在MySQL实例的启动过程中对InnoDB表存储引擎的处理过程。

在关闭时,参数innodb_fast_shutdown影响着表的存储引擎为InnoDB的行为。该参数可取值0、1、2。

0表示当MySQL关闭时,InnoDB需要完成所有的full purge和merge insert buffer操作,这会需要一些时间,有时甚至需要几个小时来完成。如果在做InnoDB plugin升级,通常需要将这个参数调为0,然后再关闭数据库。

1是该参数的默认值,表示不需要完成上述的full purge和merge insert buffer操作,但是在缓冲池中的数据脏页写回磁盘,而是将日志都写入日志文件。这样不会有任何事物会丢失,但是MySQL数据库下次启动时,会执行恢复操作。

当正常关闭MySQL数据库时,下一次启动应该会很正常。但是,如果没有正常地关闭数据库,如用kill命令关闭数据库,在MySQL数据库运行过程中重启了服务器,或者在关闭数据库时将参数innodb_fast_shutdown设为了2,MySQL数据库下次启动时都会对InnoDB存储引擎的表执行恢复操作。

而参数innodb_force_recovery影响了整个InnoDB存储引擎的恢复状况。该值默认为0,表示当需要恢复时执行所有的恢复操作。当不能进行有效恢复时,如数据页发生了corruption时,MySQL数据库可能会宕机,并把错误写入错误日志中。如果在某些情况下,我们可能并不需要执行完整的恢复操作,我们自己知道如何进行恢复。比如正在对一个表执行alter table操作,这时意外发生了,数据库重启时会对InnoDB表执行回滚操作。对于一个大表,这需要很长时间,甚至可能几个小时。这时我们可以自行进行恢复,例如可以把表删除,从备份中重新将数据导入表中,这些操作的速度可能要远远快于回滚操作。

innodb_force_recovery还可以设置6个非零值:1-6。大的数字包含了前面所有小数字的影响,具体情况如下。

1:忽略检查到的corruption页。

2:阻止主线程的运行,如主线程需要执行full purge操作,会导致crash。

3:不执行事务回滚操作。

4:不执行插入缓冲的合并操作。

5:不查看撤销日志(undo log),innodb存储引擎会将未提交的事务视为已提交。

6:不执行前滚操作。

需要注意的是,当设置参数innodb_force_recovery大于0后,可以对表进行select、create、drop操作,但insert、update或者delete这类操作时不允许的。

四、InnoDB版本信息

InnoDB存储引擎从MySQL5.1开始就采用了插件式方式存在于MySQL中,而现在所有的存储引擎都是真正的插件式了。这样设计的好处是,如果发现一个InnoDB存储引擎的BUG,你能做的就是等待MySQL新版本的发布,InnoDB公司本身对此只能通过补丁的形式来解决,你还需要重新编译一次MySQL才行。现在,你可以得到一个新版本的InnoDB,用来替代有BUG的版本。对于新版本的InnoDB你可以把它看着是一个新版本的InnoDB Plugin存储引擎,因为它还带来了一系列新的特性,比如快速索引重建、更好的多核性能、新的页结构、页压缩功能等等。

另外MySQL中查看innodb版本的方法

root@localhost [(none)]>select * from information_schema.plugins where plugin_name='innodb'\G;
*************************** 1. row ***************************
           PLUGIN_NAME: InnoDB
        PLUGIN_VERSION: 5.7
         PLUGIN_STATUS: ACTIVE
           PLUGIN_TYPE: STORAGE ENGINE
   PLUGIN_TYPE_VERSION: 50719.0
        PLUGIN_LIBRARY: NULL
PLUGIN_LIBRARY_VERSION: NULL
         PLUGIN_AUTHOR: Oracle Corporation
    PLUGIN_DESCRIPTION: Supports transactions, row-level locking, and foreign keys
        PLUGIN_LICENSE: GPL
           LOAD_OPTION: FORCE
1 row in set (0.00 sec)

或者

root@localhost [(none)]>select @@innodb_version;
+------------------+
| @@innodb_version |
+------------------+
| 5.7.19           |
+------------------+
1 row in set (0.00 sec)

InnoDB在MySQL5.5开始的版本变化:

MySQL 5.5:

MySQL Plugin Status Date
5.5.18 1.1.8 GA 11/16/2011
5.5.17 1.1.8 GA 10/19/2011
5.5.16 1.1.8 GA 09/15/2011
5.5.15 1.1.8 GA 07/28/2011
5.5.14 1.1.8 GA 07/05/2011
5.5.13 1.1.7 GA 05/31/2011
5.5.12 1.1.6 GA 05/05/2011
5.5.11 1.1.6 GA 04/07/2011
5.5.10 1.1.5 GA 03/15/2011
5.5.9 1.1.5 GA 02/07/2011
5.5.8 1.1.4 GA 12/03/2010
5.5.7 1.1.3 GA 10/14/2010
5.5.6 1.1.2 GA 09/13/2010
5.5.5 1.1.1 Early Adopter 06/06/2010 *3
5.5.4 1.1.0 Beta 04/09/2010 *2
5.5.3 1.0.6 RC 03/24/2010
5.5.2 1.0.6 RC 02/12/2010
5.5.1 1.0.6 RC 01/04/2010
5.5.0 1.0.5 RC 12/07/2009 *1
*1: The InnoDB Plugin is included in MySQL 5.5 releases as the built-in version of InnoDB.
*2: InnoDB has been upgraded to version 1.1. This version is considered of Beta quality.
*3: InnoDB has been upgraded to version 1.1.1. This version is considered of “early adopter” quality.

下面是官方摘取的Innodb版本变更信息:
The InnoDB version number. Starting in MySQL 5.6.11, separate version numbering for InnoDB is discontinued and this value is the same the version number of the server.
【官方文档连接:innodb_version

MySQL InnoDB历史发展


如果您觉得本站对你有帮助,那么可以收藏和推荐本站,帮助本站更好地发展,在此谢过各位网友的支持。
转载请注明原文链接:MySQL InnoDB历史发展
喜欢 (1)
SEian.G
关于作者:
用心去记录工作,用心去感受生活,用心去学着成长;座右铭:苦练七十二变,笑对八十一难
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址