MySQL InnoDB

MySQL InnoDB引擎

Posted by Bug1024 on March 7, 2017

MySQL实例

在Unix上,启动一个MySQL实例通常会产生两个进程,mysqld 就是真正的数据库服务守护进程,而mysqld_safe是一个用于检查和设置mysqld启动的控制程序,它负责监控于重启。

数据存储

在InnoDB存储引擎中,所有的数据都被逻辑地存放在表空间中,表空间(tablespace)是存储引擎中最高的存储逻辑单位,在表空间的下面又包括段(segment)、区(extent)、页(page)

存储表

MySQL使用InnoDB存储表时,会将表的定义和数据索引等信息分开存储,其中前者存储在.frm 文件中,后者存储在.ibd 文件中

存储记录

与现有的大多数存储引擎一样,InnoDB 使用页作为磁盘管理的最小单位;数据在 InnoDB 存储引擎中都是按行存储的,每个 16KB 大小的页中可以存放 2-200 行的记录。

聚集索引

InnoDB 存储引擎中的表都是使用索引组织的,也就是按照键的顺序存放;聚集索引就是按照表中主键的顺序构建一颗 B+ 树,并在叶节点中存放表中的行记录数据。

辅助索引

数据库将所有的非聚集索引都划分为辅助索引,辅助索引也是通过B+树实现的,但是它的叶节点并不包含行记录的全部数据,仅包含索引中的所有键和一个用于查找对应行记录的『书签』,在InnoDB中这个书签就是当前记录的主键。

并发控制机制

  • 乐观锁是一种思想,它其实并不是一种真正的『锁』,它会先尝试对资源进行修改,在写回时判断资源是否进行了改变,如果没有发生改变就会写回,否则就会进行重试,在整个的执行过程中其实都没有对数据库进行加锁
  • 悲观锁就是一种真正的锁了,它会在获取资源前对资源进行加锁,确保同一时刻只有有限的线程能够访问该资源,其他想要尝试获取资源的操作都会进入等待状态,直到该线程完成了对资源的操作并且释放了锁后,其他线程才能重新操作资源
  • 冲突频率和重试成本较高时更推荐使用悲观锁,而需要非常高的响应速度并且并发量非常大的时候使用乐观锁就能较好的解决问题,在这时使用悲观锁就可能出现严重的性能问题;在选择并发控制机制时,需要综合考虑上面的四个方面(冲突频率、重试成本、响应速度和并发量)进行选择

  • 共享锁(读锁):允许事务对一条行数据进行读取;
  • 互斥锁(写锁):允许事务对一条行数据进行删除或更新;

为什么MyISAM读更快“快”

INNODB在做SELECT的时候,要维护的东西比MYISAM引擎多很多:

  • 数据块,InnoDB要缓存,MyISAM只缓存索引块, 这中间还有换进换出的减少
  • InnoDB寻址要映射到块,再到行,MYISAM记录的直接是文件的OFFSET,定位比INNODB要快
  • InnoDB还需要维护MVCC (Multi-Version Concurrency Control)多版本并发控制,虽然你的场景没有,但他还是需要去检查和维护

常见误区

count(column) 和 count(*) 一样

  • count(column) 是表示结果集中有多少个column字段不为空的记录
  • count(*) 是表示整个结果集有多少条记录

select a,b from 比 select a,b,c from … 可以让数据库访问更少的数据量

实际上,大多数关系型数据库都是按照行(row)的方式存储,而数据存取操作都是以一个固定大小的IO单元(被称作 block 或者 page)为单位,一般为4KB,8KB… 大多数时候,每个IO单元中存储了多行,每行都是存储了该行的所有字段(lob等特殊类型字段除外)。 所以,我们是取一个字段还是多个字段,实际上数据库在表中需要访问的数据量其实是一样的。 当然,也有例外情况,那就是我们的这个查询在索引中就可以完成,也就是说当只取 a,b两个字段的时候,不需要回表,而c这个字段不在使用的索引中,需要回表取得其数据。在这样的情况下,二者的IO量会有较大差异。

order by 一定需要排序操作

引数据实际上是有序的,如果我们的需要的数据和某个索引的顺序一致,而且我们的查询又通过这个索引来执行,那么数据库一般会省略排序操作,而直接将数据返回,因为数据库知道数据已经满足我们的排序需求了