MySQL学习笔记--常用存储引擎InnoDB与MyISAM总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 一、MyISAM
    • 特性
      • 1. 并发性与锁级别
      • 2. 表损坏修复
      • 3. MyISAM表支持的索引
      • 4. MyISAM表支持压缩
    • 限制
      • 1. 版本 < MySQL5.0时单表默认最大为4G
    • MyISAM适用场景
  • 二、InnoDB
    • 系统表空间 vs 独立表空间
      • 1. 表空间文件的收缩
        • a. 系统表空间
        • b. 独立表空间
      • 2. 对IO的影响
        • a. 系统表空间
        • b. 独立表空间
    • 把系统表空间改成独立表空间
    • InnoDB怎样实现的ACID特性
      • 1. Redo Log
        • a. 重做日志缓冲区
        • b. 重做日志文件
      • 2. Undo Log
    • InnoDB支持行级锁
    • InnoDB状态检查
    • InnoDB适用场景
  • 三、锁的基本概念
    • 什么是锁?
    • 锁的分类
    • 锁的粒度
      • 1. 表级锁
      • 2. 行级锁
    • 阻塞和死锁


一、MyISAM

MySQL5.5之前版本默认存储引擎  
MySQL大部分系统表、临时表使用的存储引擎

临时表:在排序、分组等操作中,当数量超过一定大小后,由查询优化器建立的临时表

MySQL学习笔记--常用存储引擎InnoDB与MyISAM总结_第1张图片

  • frm:表结构信息
  • MYD:数据信息(MyISAM存储引擎特有)
  • MYI:索引信息(MyISAM存储引擎特有)

MyISAM存储引擎表由MYD(数据文件)和MYI(索引文件)组成。

特性

1. 并发性与锁级别

MyISAM使用的是表级锁,在对表中数据进行修改时,会对整个表进行加锁。在对表中数据进行读取时,也需要对表加共享锁。读取和写入操作是互斥的。在一些情况下,当我们对表中数据进行读取时,也可以在表的末尾加上数据。

MyISAM对于读写混合的并发性不是很好,如果只是读的操作的话,并发性是可以接受的。因为共享锁不会阻塞共享锁。

2. 表损坏修复

MyISAM支持对由于意外关闭而损坏的MyISAM表进行修复操作。(这里指的修复不是事务恢复,因为MyISAM就不是事务型的存储引擎,也没有进行事务恢复所需要的相关日志。)

要注意对MyISAM表进行数据修复可能会导致数据丢失

  • check table tablename (对表进行检查)
  • repair table tablename (对表进行恢复)

除了repair能对MyISAM表进行修复,MySQL还提供了一个命令行工具myisamchk,也可以对MyISAM表进行修复。要注意使用这个工具对MyISAM表修复的话,需要停止MySQL服务,否则容易造成更大的损坏。

3. MyISAM表支持的索引

MyISAM支持全文索引,在MySQL5.7之前版本中唯一原生支持全文索引的官方存储引擎。

4. MyISAM表支持压缩

对于一个导入数据后不会再做修改操作的表,我们可以对这样的表做压缩操作,可以减少磁盘IO。
可以使用myisampack命令来压缩表中的数据,由于表中数据是独立进行压缩的,所以读取单行数据的时候不必对整个表进行解压。

限制

1. 版本 < MySQL5.0时单表默认最大为4G

如果需要存储大表,则需要修改MAX_Rows(最大行数)和AVG_ROW_LENGTH(平均行长度)

对于大表来说,这两个参数的修改会导致整个表的重建,会需要一些时间。

版本 > MySQL5.0时单表默认最大为256TB

MyISAM适用场景

  • 非事务型应用(数据仓库、报表类的应用等)
  • 只读类应用
  • 空间类应用(支持空间函数,可以存GPS之类的数据)

二、InnoDB

MySQL5.5及之后的默认存储引擎  
InnoDB是事务型引擎,支持事务的ACID特性的  

InnoDB使用表空间进行数据存储

innodb_file_per_table
    ON:独立表空间,为每个InnoDB表创建文件--tablename.ibd
    OFF:系统表空间,把数据存储到共享表空间--ibdataX(“X”是数字)

在MySQL5.6之前的innodb_file_per_table是OFF

系统表空间 vs 独立表空间

1. 表空间文件的收缩

a. 系统表空间

在一个繁忙的系统中,系统表空间在不断增长,一旦磁盘空间出现不足,就需要在系统中删除不需要的数据。
但是在删除了之后,会发现系统表空间并不会缩小,这个时候会出现大量的磁盘碎片。要收割系统表空间的唯一方法就是把数据库中所有InnoDB表导出,删除InnoDB相关的系统表空间文件后,重启数据库服务器来进行表空间的重建,再导入数据。

使用系统表空间进行数据存储,面临的问题就是无法很容易收缩系统文件,造成大量的空间浪费,磁盘碎片,从而降低系统的性能。

b. 独立表空间

独立表空间可以通过optimize table命令收缩系统文件。
这样就比对整个系统进行表空间重建要快得多,而且不用重启数据库服务器

结论:使用系统表空间比使用独立表空间要好得多。

2. 对IO的影响

a. 系统表空间

对于系统表空间来说,由于只有一个文件,对多个表进行数据刷新时,从文件系统层面来说是顺序进行的,所以会产生一定的IO瓶颈。

b. 独立表空间

对于独立表空间来说,每个表都有自己的表空间文件,在数据写入时,可以利用多个文件增加IO处理的性能。

结论:对于频繁写入操作的系统来说,不太适合使用系统表空间来统一存储数据,而是要使用独立表空间。

把系统表空间改成独立表空间

步骤

  1. 使用mysqldump导出所有数据库表数据
  2. 停止MySQL服务,修改innodb_file_per_table参数,并删除InnoDB相关文件
  3. 重启MySQL服务,重建InnoDB系统表空间
  4. 重新导入数据

把系统表空间迁移到独立表空间后,选择系统表空间里还有什么内容呢?

  • InnoDB数据字典信息(表、列、索引、外键等)。对比frm文件是MySQL服务层产生的,是MySQL服务层的数据字典,是与存储引擎无关的;系统表空间的数据字典存储的是存储引擎产生的与存储引擎相关的一些内容,可以保障事务的一些安全性,另外InnoDB存储引擎没有使用上层的一些类型,而是自己封装。frm文件只是一个简单的二进制文件,InnoDB数据字典是使用B树来进行数据管理的。
  • Undo回滚段与InnDB临时表(5.7版本以后这两种都可以从系统表空间中移出,很多默认还是存在系统表空间中)

InnoDB怎样实现的ACID特性

使用了两个特殊的日志:

  • 重做日志Redo Log --实现–> 事务的持久性
  • 回滚日志Undo Log --实现–> 原子性 一致性

Redo Log 存储的是已提交的事务,Undo Log 存储的是未提交的事务。

1. Redo Log

Redo Log 由两部分组成:

内存中的重做日志缓冲区 + 文件系统中的重做日志文件

a. 重做日志缓冲区
show variables like 'innodb_log_buffer_size';

innodb_log_buffer_size 设置重做日志缓冲区的大小,单位为字节。
因为每隔一秒钟就会把缓冲区刷新到硬盘上,所以不需要设置太大。

b. 重做日志文件
show variables like 'innodb_log_files_in_group';

innodb_log_files_in_group 这个参数决定了会产生几个logfile文件
innodb_log_files_in_group决定产生几个ib_logfileX文件

2. Undo Log

帮助未提交事务进行回滚和实现MVCC,

当对InnoDB表中的数据进行修改时,不仅产生 Redo Log 还会产生 Undo Log,这样如果用户的事务或者语句失败因为某种原因失败,或者使用ubat语句回滚时,就需要使用到 Undo Log 中的信息了。

Redo Log 基本是顺序写入的,在数据库运行时,不需要对 Redo Log 进行读取操作。
而 Undo Log 是需要进行随机的读写的,MySQL5.6版本以后,可以独立于系统表空间而存在,可以把 Undo Log 存储在固态存储设备上,以获得更好的性能。

InnoDB支持行级锁

行级锁的特点是,在进行写操作时我们所用的资源更少,这样能支持的并发就会更多。
InnoDB支持的行级锁是由存储引擎实现的,MySQL服务层完全不了解存储引擎中锁的实现方式。

InnoDB状态检查

show engine innodb status

InnoDB适用场景

适合大多数OLTP应用

5.7之后InnoDB就可以支持全文索引与空间函数了

三、锁的基本概念

什么是锁?

锁是数据库系统区别于文件系统的重要特性
锁的主要作用是管理共享资源的并发访问
锁用于实现事务的隔离性

锁的分类

  • 共享锁(也称读锁)
  • 独占锁(也称写锁、排它锁)。写锁会阻塞其他的读锁或写锁,出于数据完整性的考虑,在给定时间里只有一个线程能执行写入,并防止其他用户读取正在写入的资源,实现事务的隔离性。
\ 写锁 读锁
写锁 不兼容 不兼容
读锁 不兼容 兼容

对于InnoDB来说,读锁和写锁都是行锁。

InnoDB的锁的实现要比这个更复杂。

一个例子:

连接一:开启一个事务更新某一行,不提交。
连接二:查询该行。
发现连接二的查询并没有被连接一阻塞。

这就是InnoDB的独到之处,在第二个连接中查询到的结果其实是存储在 undo log 中的版本。

锁的粒度

锁的粒度就是指被加锁单元的最小单位。(行、页、表…)

最理想的粒度就是只对需要修改的数据进行精确的锁定,相互之间不产生阻塞,并发性自然也就会更高

1. 表级锁

MySQL中最基本,开销最小的策略,开销小那么同时并发性也就低

InnoDB中的表级锁通常是由MySQL服务层实现的。虽然InnoDB实现的是行级锁,但是一些情况下MySQL服务层还是会加表级锁。

比如 lock table操作时
例子:
连接一:

lock table tablename write;

连接二:

select * from tablename

发现连接二被阻塞
连接一:

unlock tables;

然后第二个连接的操作被执行

2. 行级锁

行级锁可以最大程度上支持并发处理,同时锁的开销也比表级锁大。
行级锁只在存储引擎层实现,MySQL服务层并没有对行级锁做任何实现。

阻塞和死锁

什么是阻塞?

因为不同锁之间的兼容性的关系,有些时刻一个事务中的锁需要等待另一个事务中的锁释放占用的资源,而形成阻塞。

阻塞是为了确保事务的可以并发且可以正常运行,当一个系统中出现大量阻塞,往往也意味着系统中存在着问题。
过多的阻塞可以使数据库连接大量堆积,占用大量系统资源,使系统性能整体下降。

什么是死锁?

两个或两个以上的事务,在执行过程中相互占用对方等待的资源,产生的一种异常。

数据库系统会自动发现死锁,并且在多个死锁的事务中选出资源占用最少的事务来进行回滚操作,这样来使其他事务正常运行。
死锁是可以由系统自动处理的。有少量的死锁并不会对系统造成什么影响,但是如果一个系统中频繁出现大量死锁则还是需要留意了。

你可能感兴趣的:(MySQL,mysql)