MySQL数据库——存储引擎

一、MySQL存储引擎

1.存储引擎的概念

  1. MySQL中的数据用各种不下同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎。
  2. 存储引擎是MySQL将数据存储在文件系统中的存储方式或者存储格式。
  3. 存储引擎是MySQL数据库中的组件,负责执行实际的数据I/O操作。
  4. MySQL系统中,存储引擎处于文件系统之上,在数据保存到数据文件之前会传输到存储引擎,之后按照各个存储引擎的存储格式进行存储。

2.常用存储引擎

常用存储引擎:InnoDB、MyISAM

MyISAM: 不支持事务和外键约束,占用资源较小,访问速度快,表级锁定,支持全文索引,适用于不需要事务处理,单独写入或查询的应用场景。
InnoDB: 支持事务处理、外键约束,缓存能力较好,支持行级锁定,读写并发能力较好,5.5版本后支持全文索引,适用于一致性要求高、数据更新频繁的应用场景。

3.存储引擎的分类

存储引擎 分类
MyISAM Mysql 5.5之前的默认数据库引擎,最为常用。拥有较高的插入,查询速度,但不支持事务;
InnoDB 事务型速记的首选引擎,支持ACID事务,支持行级锁定,MySQL5.5成为默认数据库引擎;
Memory 所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在MYSQL重新启动是会丢失;
Archive 非常适合存储大量的独立的,作为历史记录的数据。因为它们不经常被读取。Archive 拥有高效的插入速度,但其对查询的支持相对较差;
Federated 将不同的 MySQL 服务器联合起来,逻辑上组成一个完整的数据库。非常适合分布式应用;
CSV 逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个 .csv 文件。这是一种普通文本文件,每个数据行占用一个文本行。CSV 存储引擎不支持索引。
BlackHole 黑洞引擎,写入的任何数据都会消失,一般用于记录 binlog 做复制的中继;
ERFORMANCE_SCHEMA 存储引擎该引擎主要用于收集数据库服务器性能参数;
Mrg_Myisam Merge 存储引擎,是一组MyIsam的组合,也就是说,他将MyIsam引擎的多个表聚合起来,但是他的内部没有数据,真正的数据依然是MyIsam引擎的表中,但是可以直接进行查询、删除更新等操作;

在这里插入图片描述

4.企业选择存储引擎依据

  1. 需要考虑每个存储引擎提供了哪些不同的核心功能及应用场景。

  2. 支持的字段和数据类型
    所有引擎都支持通用的数据类型
    但不是所有的弓|擎都支持其它的字段类型,如二进制对象.

  3. 锁定类型:不同的存储引擎支持不同级别的锁定
    表锁定:MyISAM 支持
    行锁定:InnoDB 支持

二、MyISAM 存储引擎

1 MyISAM的相关了解

  1. MylSAM不支持事务,也不支持外键约束,只支持全文索引,数据文件和索引文件是分开保存的。
  2. 访问速度快,对事务完整性没有要求。
  3. MylSAM适合查询、插入为主的应用。
  4. MylSAM在磁盘.上存储成三个文件,文件名和表名都相同,但是扩展名分别为:

.frm文件存储表结构的定义
数据文件的扩展名为.MYD (MYData)
索引文件的扩展名是.MYI (MYIndex)

2 MyISAM的特点

  1. 表级锁定形式,数据在更新时锁定整个表
  2. 数据库在读写过程中相互阻塞:
  3. 会在数据写入的过程阻塞用户数据的读取
  4. 也会在数据读取的过程中阻塞用户的数据写入数据单独写入或读取,速度过程较快且占用资源相对少。

3 MyISAM表支持3种不同的存储格式

(1)静态(固定长度)表
静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。

(2)动态表
动态表包含可变字段,记录不是固定长度的,这样存储的优点是占用空间较少,但是频繁的更新、删除记录会产生碎片,需要定期执行OPTIMIZE TABLE语句或myisamchk-r命令来改善性能,并且出现故障的时候恢复相对比较困难(因为会产生磁盘碎片,而且存储空间不是连续的)。

(3)压缩表
压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支。(压缩的过程中会占用CPU性能

4.MyISAM适用的生产场景

  • 公司业务不需要事务的支持
  • 单方面读取或写入数据比较多的业务
  • MyISAM存储引擎数据读写都比较频繁场景不适合
  • 使用读写并发访问相对较低的业务
  • 数据修改相对较少的业务
  • 对数据业务一致性要求不是非常高的业务
  • 服务器硬件资源相对比较差

三、InnoDB 存储引擎

1 InnoDB的相关了解

  1. 支持事务,支持4个事务隔离级别
  2. MySQL从5.5.5版本开始,默认的存储引擎为InnoDB
  3. 读写阻塞与事务隔离级别相关
  4. 能非常高效的缓存索引和数据
  5. 表与主键以簇的方式存储 BTREE
  6. 支持分区、表空间,类似oracle数据库
  7. 支持外键约束,5.5前不支持全文索引,5.5后支持全文索引
  8. 对硬件资源要求还是比较高的场合
  9. 行级锁定,但是全表扫描仍然会是表级锁定
  10. 使用like进行模糊查询时,会进行全表扫描,锁定整个表。
  11. 对没有创建索引的字段进行查询,也会进行全表扫描锁定整个表。
  12. 使用索引进行查询,则是行级锁定。

2 InnoDB的特点

  1. InnoDB中不保存表的行数,如 select count() from table; 时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。需要注意的是当count()语句包含where条件时MyISAM也需要扫描整个表。
  2. 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立组合索引。
  3. delete清空整个表时,InnoDB 是一行一 行的删除,效率非常慢。MyISAM则会重建表。

3.InnoDB适用的生产场景

  • 业务需要事务的支持。
  • 行级锁定对高并发有很好的适应能力,但需确保查询是通过索引来完成。
  • 业务数据更新较为频繁的场景。(如:论坛,微博等。)
  • 业务数据一致性要求较高。(如:银行业务。)
  • 硬件设备内存较大,利用InnoDB较好的缓存能力来提高内存利用率,减少磁盘IO的压力。

四、MyISAM和InnoDB的区别

MyISAM:不支持事务和外键约束,占用资源较小,访问速度快,表级锁定,支持全文索引,适用于不需要事务处理,单独写入或查询的应用场景。 存储格式: 表名.frm(表结构文件) 表名.MYD(数据文件) 表名.MYI(索引文件)

InnoDB:支持事务处理、外键约束,缓存能力较好,支持行级锁定,读写并发能力较好,5.5版本后支持全文索引,适用于一致性要求高、数据更新频繁的应用场景。表名.frm(表结构文件) 表名.idb(表数据文件/索引文件) db.opt(表属性文件)

功能 MyISAM InnoDB
存储限制 256TB 64TB
事务 不支持 支持
全文索引 支持 不支持
B树索引 支持 支持
哈希索引 不支持 不支持
集群索引 不支持 支持
数据索引 不支持 支持
数据压缩 支持 不支持
空间使用率
外键 不支持 支持

五、Mysql存储引擎的管理

1.查看系统支持的存储引擎

show engines;
在这里插入图片描述

2.查看表使用的存储引擎

方法一:
show table status from 库名 where name='表名'\G

方法二:
use 库名;
show create table 表名;
在这里插入图片描述

3.修改存储引擎

方法一:通过 alter table 修改
use 库名;
alter table 表名 engine=MyISAM;
在这里插入图片描述

方法二:通过修改 /etc/my.cnf 配置文件,指定默认存储引擎并重启服务

vim /etc/my.cnf
......
[mysqld]
......
default-storage-engine=INNODB

systemctl restart mysql.service
注意:此方法只对修改了配置文件并重启mysql服务后新创建的表有效,已经存在的表不会有变更。

在这里插入图片描述

方法三:通过 create table 创建表时指定存储引擎
use 库名;
create table 表名(字段1 数据类型,…) engine=MyISAM;
在这里插入图片描述

六、InnoDB的索引和锁的关系

InnoDB行锁是通过给索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁(一般称为表锁)。

1.表锁

1)
delete from t1 where id=1;
如果id字段是主键,innodb对于主键使用了聚簇索引,会直接锁住整行记录。

2)
delete from t1 where name=‘aaa’;
如果name字段是普通索引,会先锁住索引的两行,接着会锁住相应主键对应的记录。

3)
delete from t1 where age=23;
如果age字段没有索引,会使用全表扫描过滤,这时表上的各个记录都将加上锁。

2.死锁

死锁一般是事务相互等待对方资源,最后形成环路造成的。

案例:
create table t1(id int primary key, name char(3), age int);
insert into t1 values(1,'aaa',22);
insert into t1 values(2,'bbb',23);
insert into t1 values(3,'aaa',24);
insert into t1 values(4,'bbb',25);
insert into t1 values(5,'ccc',26);
insert into t1 values(6,'zzz',27);

session 1								session 2
begin;									begin;
delete from t1 where id=5;	
										select * from t1 where id=1 for update;
delete from t1 where id=1; #死锁发生	

在这里插入图片描述
如何尽可能避免死锁?

  1. 使用更合理的业务逻辑,以固定的顺序访问表和行。
  2. 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。
  3. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
  4. 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。
  5. 为表添加合理的索引。如果不使用索引将会为表的每一行记录添加上锁,死锁的概率大大增大。

猜你喜欢

转载自blog.csdn.net/weixin_67300995/article/details/131310207