首页 > 数据库技术 > 详细

MySQL-innodb存储引擎

时间:2019-10-08 18:51:13      阅读:92      评论:0      收藏:0      [点我收藏+]

一、InnoDB存储引擎介绍

1)MySQL从5.5版本开始将InnoDB作为默认存储引擎,该存储引擎是第一个完整支持事务ACID特性的存储引擎,且支持数据行锁,多版本并发控制(MVCC),外键,以及一致性非锁定读

2)作为默认存储引擎,也就意味着默认创建的表都会使用此存储引擎,除非使用ENGINE=参数指定创建其他存储引擎的表。

1.1、InnoDB的关键属性

InnoDB的关键属性包括:
  1. ACID事务特性支持,包括commit,rollback以及crash恢复的能力
  2. 行级别锁以及多版本并发控制MVCC
  3. 利用主键的聚簇索引(clustered index)在底层存储数据,以提升对主键查询的IO性能
  4. 支持外键功能,管理数据的完整性

1.2、ACID模型

ACID模型是关系型数据库普遍支持的事务模型,用来保证数据的一致性,其中的ACID分别代表:

  • A:atomicity原子性:事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生
  • C:consistency一致性:事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。这是说数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性
  • I:isolation独立性多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果
  • D:durability持续性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚
举例来说,比如银行的汇款1000元的操作,简单可以拆分成A账户的余额-1000,B账户的余额+1000,还要分别在A和B的账户流水上记录余额变更日志,这四个操作必须放在一个事务中完成,否则丢失其中的任何一条记录对整个系统来说都是不完整的。
 
对上述例子来说,
原子性体现在要么四条操作每个都成功,意味着汇款成功,要么其中某一个操作失败,则整个事务中的四条操作都回滚,汇款失败;一致性表示当汇款结束时,A账户和B账户里的余额变化和操作日志记录是可以对应起来的;
独立性表示当汇款操作过程中如果有C账户也在往B账户里汇款的话,两个事务相互不影响,即A->B有四个独立操作,C->B有四个独立操作;
持久性表示当汇款成功时,A和B的余额就变更了,不管是数据库重启还是什么原因,该数据已经写入到磁盘中作为永久存储,不会再变化,除非有新的事务 

#其中事务的隔离性是通过MySQL锁机制实现 原子性,一致性,持久性则通过MySQL的redo和undo日志记录来完成
#1.隐时开启事务set autocommit=off;
mysql> show variables like ‘%autocommit%‘;
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+

mysql> select * from score;
+------+-----------+-------+
| sid  | course_id | score |
+------+-----------+-------+
|    1 |         1 |    76 |
|    1 |         2 |    90 |
|    1 |         3 |    82 |
|    1 |         5 |    56 |
|    2 |         2 |    78 |
|    2 |         4 |    92 |
|    2 |         3 |    77 |
|    2 |         5 |    65 |
|    3 |         1 |    48 |
|    3 |         2 |    95 |
|    3 |         3 |    75 |
|    3 |         4 |    89 |
|    3 |         5 |    92 |
+------+-----------+-------+

mysql> set autocommit=off;
mysql> update score set score=90 where sid =1;
mysql> select * from score;
+------+-----------+-------+
| sid  | course_id | score |
+------+-----------+-------+
|    1 |         1 |    90 |
|    1 |         2 |    90 |
|    1 |         3 |    90 |
|    1 |         5 |    90 |
|    2 |         2 |    78 |
|    2 |         4 |    92 |
|    2 |         3 |    77 |
|    2 |         5 |    65 |
|    3 |         1 |    48 |
|    3 |         2 |    95 |
|    3 |         3 |    75 |
|    3 |         4 |    89 |
|    3 |         5 |    92 |
+------+-----------+-------+

#rollback或者commit
mysql> rollback;
mysql> select * from score;
+------+-----------+-------+
| sid  | course_id | score |
+------+-----------+-------+
|    1 |         1 |    76 |
|    1 |         2 |    90 |
|    1 |         3 |    82 |
|    1 |         5 |    56 |
|    2 |         2 |    78 |
|    2 |         4 |    92 |
|    2 |         3 |    77 |
|    2 |         5 |    65 |
|    3 |         1 |    48 |
|    3 |         2 |    95 |
|    3 |         3 |    75 |
|    3 |         4 |    89 |
|    3 |         5 |    92 |
+------+-----------+-------+

#2.显示开启事务
start transaction;

1.3、InnoDB多版本控制(MVCC)

1)为保证并发操作和回滚操作,InnoDB会将修改前的数据存放在回滚段中。

2)InnoDB会在数据库的每一行上额外增加三个字段以实现多版本控制

  • DB_TRX_ID:用来存放针对该行最后一次执行insert、update操作的事务ID,而delete操作也会被认为是update,只是会有额外的一位来代表事务为删除操作;
  • DB_ROLL_PTR:指针指向回滚段里对应的undo日志记录;
  • DB_ROW_ID:代表每一行的行ID。

3)回滚段中的undo日志记录只有在事务commit提交之后才会被丢弃,为避免回滚段越来越大,要注意及时执行commit命令

技术分享图片

#在两个数据库链接下实验多版本控制

链接1:mysql> start transaction;
链接2:mysql> start transaction;
链接1:mysql> update score set score=88 where sid=1;
链接2:mysql> select * from score where sid=1; ###链接1锁数据未释放,链接2也能访问相同数据
链接1:mysql>commit;
链接2:mysql> select * from score where sid=1; ###链接1锁释放,但链接2访问到的数据依然是之前的数据
链接2:mysql> commit;
链接2:mysql> select * from score where sid=1; ###链接2提交之后,再访问到的数据是修改后的数据

1.4、查看存储引擎情况

在MySQL实例中执行show engines命令查看存储引擎情况 Support=YES代表当前支持的存储引擎,DEFAULT代表默认存储引擎

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

1.5、InnoDB表数据存储格式

技术分享图片

技术分享图片

特点:

  • 根据主键寻址速度很快
  • 主键值递增的insert插入效率较好
  • 主键值随机insert插入操作效率差

二、InnoDB体系结构

技术分享图片

技术分享图片

2.1、buffer pool缓存池

1)buffer pool缓存池是InnoDB在内存中开辟的用来缓存表数据和索引数据的区域,一般 可以设置为50%~80%的物理内存大小,通过对经常访问的数据放置到内存当中来加快访 问速度。

2)Buffer pool以page页的格式组成,页之间组成list列表,并通过LRU算法(最近最少使用算法)对长久不使用的页进行置换。

3)数据的读写需要经过缓存(缓存在buffer pool 即在内存中) 数据以整页(16K)位单位读取到缓存中 缓存中的数据以LRU策略换出(最少使用策略) IO效率高,性能好

技术分享图片技术分享图片

2.1.1、Adaptive Hash Index(自适应哈希索引)

1)Adaptive Hash index属性使得InnoDB更像是内存数据库。该属性通过innodb_adapitve_hash_index开启,也可以通过—skip-innodb_adaptive_hash_index参数关闭

mysql> show variables like ‘%hash%‘;
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| innodb_adaptive_hash_index       | ON    |
| innodb_adaptive_hash_index_parts | 8     |
| metadata_locks_hash_instances    | 8     |
+----------------------------------+-------+

2)InnoDB存储引擎会监控对表上索引的查找,如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称之为自适应(adaptive) 的。自适应哈希索引通过缓冲池的B+树构造而来,因此建立的速度很快。而且不需要将整个表都建哈希索引,InnoDB存储引擎会自动根据访问的频率和模式 来为某些页建立哈希索引

3)哈希(hash)是一种非常快的等值查找方法,在一般情况下这种查找的时间复杂度为O(1),即一般仅需要一次查找就能定位数据。 而B+树的查找次数,取决于B+树的高度,在生产环境中,B+树的高度一般3-4层,故需要3-4次的查询。 innodb会监控对表上个索引页的查询。如果观察到建立哈希索引可以带来速度提升,则自动建立哈希索引,称之为自适应哈希索引(Adaptive Hash Index,AHI)。

4)AHI有一个要求,就是对这个页的连续访问模式必须是一样的。 例如对于(a,b)访问模式情况:

  • where a = xxx
  • where a = xxx and b = xxx

5)AHI启动后,读写速度提高了2倍,辅助索引的连接操作性能可以提高5倍。 AHI,是数据库自动优化的,DBA只需要指导开发人员去尽量使用符合AHI条件的查询,以提高效率

2.2、Redo log buffer

Redo log buffer是一块用来存放写入redo log文件内容的内存区域,内存的大小由innodb_log_buffer_size参数确定。该buffer的内容会定期刷新到磁盘的redo log文件中。

1)参数innodb_flush_log_at_trx_commit决定了刷新到文件的方式,

2)参数innodb_flush_log_at_timeout参数决定了刷新的频率。

2.3、系统表空间

1)InnoDB的系统表空间用来存放表和索引数据,同时也是doublewriter缓存,change缓存和回滚日志(undo log)的存储空间,系统表空间是被多个表共享的表空间

默认情况下,系统表空间只有一个系统数据文件,名为ibdata1。系统数据文件的位置和个数由参数innodb_data_file_path参数决定。

mysql> show variables like ‘%innodb_data_file_path%‘;
+-----------------------+------------------------+
| Variable_name         | Value                  |
+-----------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
+-----------------------+------------------------+

2.4、Double  write缓存

1)Doublewrite缓存是位于系统表空间的存储区域,用来缓存InnoDB的数据页从innodb buffer pool中flush之后并写入到数据文件之前,所以当操作系统或者数据库进程在数据页写磁盘的过程中崩溃,Innodb可以在doublewrite缓存中找到数据页的备份而用来执行crash恢复。

2)数据页写入到doublewrite缓存的动作所需要的IO消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入。

3)在应用(apply)重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write

4)doublewrite组成

  • 内存中的doublewrite buffer,大小2M
  • 物理磁盘上共享表空间中连续的128个页,即2个区(extend),大小同样为2M。

5)double write原理

对缓冲池的脏页进行刷新时,不是直接写磁盘,而是会通过memcpy()函数将脏页先复制到内存中的doublewrite buffer, 之后通过doublewrite 再分两次,每次1M顺序地写入共享表空间的物理磁盘上,在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。在完成doublewrite页的写入后,再将doublewrite buffer 中的页写入各个 表空间文件中,此时的写入则是离散的。如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,innodb可以从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。

技术分享图片

2.5、Undo日志

1)Undo日志是由一系列事务的undo日志记录组成,每一条undo日志记录包含了事务数据回滚的相关原始信息,所以当其它的事务需要查看修改前的原始数据,则会从此undo日志记录中获取。Undo日志存放在回滚段中的undo日志段中。

2)默认情况下回滚段是作为系统表空间的一部分,但也可以有自己独立的undo表空间,通过设置innodb_undo_tablespaces和innodb_undo_directory两个参数。

3)Innodb支持最大128个回滚段,其中的32个用来服务临时表的相关事务操作,剩下的96个服务非临时表,每个回滚段可以同时支持1023个数据修改事务,也就是总共96K个数据修改事务。

4)Innodb_undo_logs参数用来设置回滚段的个数。

mysql> show variables like ‘%undo%%‘;
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| innodb_max_undo_log_size | 1073741824 |
| innodb_undo_directory    | ./         |
| innodb_undo_log_truncate | OFF        |
| innodb_undo_logs         | 128        |
| innodb_undo_tablespaces  | 0          |
+--------------------------+------------+

5)Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方 (这个存储数据备份的地方称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了 ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态

2.6、File-per-table表空间(独立表空间)

File-per-table表空间意味着innodb的数据表不是共享一个系统表空间,而是每个表一个独立的表空间。可以通过设置innodb_file_per_table开启此属性。开启之后每个表数据和索引数据都会默认单独存放在数据文件夹下的.ibd数据文件中。

mysql> show variables like ‘%per_table%‘;
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+

2.7、temporary表空间

1)temporary临时表空间用来存放临时表,默认情况下是在数据文件夹下的ibtmp1数据文件,此数据文件被设置为每次自动增长12MB大小,当然也可以设置innodb_temp_data_file_path来指定临时表空间文件的存放位置。

2)临时表空间文件在正常的shutdown之后会自动清除,但在crash发生时不会清除,这就需要DBA手动去删除表空间文件或重启服务器。

mysql> show variables like ‘%innodb_temp%‘;
+----------------------------+-----------------------+
| Variable_name              | Value                 |
+----------------------------+-----------------------+
| innodb_temp_data_file_path | ibtmp1:12M:autoextend |
+----------------------------+-----------------------+

3)如果发现临时表空间数据文件比较大,可以考虑重启MySQL来释放空间大小。

2.9、redo  log重做日志

1)redo日志是存在于磁盘上的文件,包括ib_logfile0和ib_logfile1两个文件常用于在crash恢复发生时将还没来得及写入到数据文件中但已经完成提交的事务在数据库初始化时重新执行一遍。

2)InnoDB对redo log buffer写入到redo log文件的方式提供了组提交(group commit)的方式,意味着针对一次写磁盘操作可以包含多个事务数据,用此方法提高性能。

3)为了IO效率,数据库修改的文件都在内存缓存中完成的;那么我们知道一旦断电,内存中的数据将消失,而数据库是如何保证数据的完整性?那就是数据持久化与事务日志

4)如果宕机了则:应用已经持久化好了的日志文件,读取日志文件中没有被持久化到数据文件里面的记录;将这些记录重新持久化到我们的数据文件中

技术分享图片

5)innodb日志持久化相关参数

①innodb_flush_log_at_trx_commit

  • 0:每秒写入并持久化一次(不安全,性能高,无论mysql或服务器宕机,都会丢数据最多1秒的数据)
  • 1:每次commit都持久化(安全,性能低,IO负担重)
  • 2:每次commit都写入内存的内存缓存,每秒再刷新到磁盘(安全,性能折中,mysql宕机数据不会丢失,服务器宕机数据会丢失最多1秒的数据

②innodb_flush_log_at_timeout:参数决定最多丢失多少秒的数据,默认是1秒

三、InnoDB存储引擎配置

3.1、启动配置

InnoDB合理的规划方法是在创建数据库实例之前就定义好数据文件,日志文件和数据页大小等相关属性

3.2、指定配置文件位置

MySQL实例启动需要依赖my.cnf配置文件,而配置文件可以存在于多个操作系统目录下 my.cnf文件的默认查找路径,从上到下找到的文件先读,但优先级逐级提升

技术分享图片

MySQL-innodb存储引擎

原文:https://www.cnblogs.com/hujinzhong/p/11636361.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!