MYSQL数据库--存储引擎

前言

MYSQL数据库--存储引擎_第1张图片

数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作。简而言之,存储引擎就是指表的类型。数据库的存储引擎决定了表在计算机中的存储方式。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以获得特定的功能。

现在许多数据库管理系统都支持多种不同的存储引擎。MySQL的核心就是存储引擎。

MySQL 提供了多个不同的存储引擎,包括处理事务安全表的引擎和处理非事务安全表的引擎。在 MySQL 中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求,可以对每一个表使用不同的存储引擎。

MySQL 5.7 支持的存储引擎有 InnoDB、MyISAM、Memory、Merge、Archive、CSV、BLACKHOLE 等。可以使用SHOW ENGINES;语句查看系统所支持的引擎类型,结果如图所示。

MYSQL数据库--存储引擎_第2张图片

Support 列的值表示某种引擎是否能使用,YES表示可以使用,NO表示不能使用,DEFAULT表示该引擎为当前默认的存储引擎。

下面简要描写几种存储引擎,后面会对其中的几种(主要是 InnoDB 和 MyISAM )进行详细讲解。像 NDB 这样的需要更多扩展性的讨论,这超出了本教程的介绍范畴,所以在教程后面对它们不会介绍太多。

存储引擎 描述
ARCHIVE 用于数据存档的引擎,数据被插入后就不能在修改了,且不支持索引。
CSV 在存储数据时,会以逗号作为数据项之间的分隔符。
BLACKHOLE 会丢弃写操作,该操作会返回空内容。
FEDERATED 将数据存储在远程数据库中,用来访问远程表的存储引擎。
InnoDB 具备外键支持功能的事务处理引擎
MEMORY 置于内存的表
MERGE 用来管理由多个 MyISAM 表构成的表集合
MyISAM 主要的非事务处理存储引擎
NDB MySQL 集群专用存储引擎

有几种存储引擎的名字还有同义词,例如,MRG_MyISAM 和 NDBCLUSTER 分别是 MERGE 和 NDB 的同义词。存储引擎 MEMORY 和 InnoDB 在早期分别称为 HEAP 和 Innobase。虽然后面两个名字仍能被识别,但是已经被废弃了。

存储引擎的概念

什么是存储引擎

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

MySQL常用的存储引擎:

  • MylSAM
  • InnoDB
    注意:一个表只能使用一个存储引擎,一个库中不同的表可以使用不同的存储引擎。

MyISAM存储引擎

MylSAM介绍

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

MylSAM的特点

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

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

静态(固定长度)表

静态表是默认的存储格式。静态表中的字段都是非可变字段,这样每个记录都是固定长度的,这种存储方式的优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。 静态格式是MyISAM表的默认存储格式。当表不包含变量长度列(VARCHAR, BLOB, 或TEXT)时,使用这个格式。每一行用固定字节数存储。静态格式是三种存储格式中最简单和最安全的,同时也是最快的ondisk格式。

基本特征:

  • CHAR列对列宽度为空间填补。
  • 快速。
  • 容易缓存。
  • 由于每个记录位置固定,崩溃后容易重建。(5)无必要重新组织,通常比动态表需要更大的磁盘空间。

动态表

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

如果一个MyISAM表包含任何可变长度 列(VARCHAR, BLOB或TEXTDynamic),或者如果一个表被用ROW_FORMAT=DYNAMIC选项来创建,动态存储格式被使用。

基本特征:

  • 除了长度少于4的列之外,所有的字符串列存储为动态。
  • 每个记录前存储一个位图,该位图表明哪一列包含空字符串(对于字符串列)或者0(对于数字列),但并不包括包含NULL值的列。而非空字符串列,则会被存为一个长度字节加字符串的内容。
  • 动态格式表在崩溃后要比静态格式表更难重建,因为一个记录可能被分为多个碎片且链接(碎片)可能被丢失。
  • 每个记录仅使用必需大小的空间。尽管如此,如果一个记录变大,它就按需要被分开成多片,造成记录碎片的后果。比如,你用扩展行长度的信息更新一行,该行就变得有碎片。在这种情况下,你可以时不时运行OPTIMIZE TABLE或myisamchk -r来改善性能。可使用myisamchk -ei来获取表的统计数据。

压缩表

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

MySQL分发版本里默认包含myisampack工具,已压缩存储格式是由它创建的只读格式。

压缩表有下列特征:

  • 压缩表占据很小的磁盘空间,最小化了磁盘用量。
  • 每个记录被单独压缩,访问开支小。
  • 可以处理固定长度或动态长度记录。

MyISAM使用的生产场景举例

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

InnoDB存储引擎

InnoDB介绍

  • 支持事务,支持4个事务隔离级别
  • MySQL从5.5.5版本开始,默认的存储引擎为InnoDB
  • 读写阻塞与事务隔离级别相关
  • 能非常高效的缓存索引和数据
  • 表与主键以簇的方式存储 BTREE
  • 支持分区、表空间,类似oracle数据库
  • 支持外键约束,5.5前不支持全文索引,5.5后支持全文索引
  • 对硬件资源要求还是比较高的场合
  • 行级锁定,但是全表扫描仍然会是表级锁定,如
    • update table set a=1 where user like ‘%zhang%’;

注:

  • 使用like进行模糊查询时,会进行全表扫描,锁定整个表。
  • 对没有创建索引的字段进行查询,也会进行全表扫描锁定整个表。
  • 使用索引进行查询,则是行级锁定。

InnoDB的特点

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

InnoDB适用生产场景分析

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

MyISAM和InnoDB的区别:

MyISAM: : 不支持事务和外键约束,占用空间较小,访问速度快,表级锁定,支持全文索引,适用于不需要事务处理、单独写入或查询的应用场景。(写入和查询不一起使用的场景)

InnoDB: : 支持事务处理、外键约束、占用空间比MyISAM 大,支持行级锁定,5.5版本后支持全文索引,读写开发能力较好,适用于需要事务处理、读写频繁,一致性要求高,数据更新频繁的应用场景。

企业选择存储引擎依据

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

2、支持的字段和数据类型

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

3、锁定类型:不同的存储引擎支持不同级别的锁定

  • 表锁定:MyISAM 支持
  • 行锁定:InnoDB 支持

查看和修改存储引擎

查看存储引擎

查看系统支持的存储引擎

show engines;

#Engine:存储引擎的名称。
#Support:YES表示引擎受支持且处于活动状态,NO表示不支持,DEFAULT表示默认存储引擎。DISABLED表示支持引擎但已将其禁用。
#Comment:存储引擎的简要说明。
#Transactions:存储引擎是否支持事务。
#XA:存储引擎是否支持XA事务。
#Savepoints:存储引擎是否支持回滚点(标记点)。

MYSQL数据库--存储引擎_第3张图片

MYSQL数据库--存储引擎_第4张图片

查看数据表使用的存储引擎

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

MYSQL数据库--存储引擎_第5张图片

方法二:
use 库名;
show create table 表名;

MYSQL数据库--存储引擎_第6张图片

修改存储引擎

方法一:alter table修改

修改当前数据表使用的存储引擎。

use 库名;
alter table 表名 engine=存储引擎名称;

eg : use school;
alter table class engine=MyISAM;   #将class表的存储引擎修改为MyISAM

注意:因为MyISAM不支持外键约束,如果数据表设置了外键,则无法修改为MyISAM。

MYSQL数据库--存储引擎_第7张图片

MyISAM不支持外键约束,如果数据表设置了外键,则无法修改为MyISAM:

MYSQL数据库--存储引擎_第8张图片

修改配置文件,指定默认存储引擎

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

创建数据表时如果没有指定存储引擎,则会使用默认存储引擎。

vim /etc/my.cnf

[mysqld]
default-storage-engine=InnoDB   #修改这一行,指定默认存储引擎为InnoDB

systemctl restart mysqld   #重启服务

MYSQL数据库--存储引擎_第9张图片

create table 创建表时指定存储引擎

use 库名;
create table 表名(字段1 数据类型,…)  engine=存储引擎名称;

eg : use school;
create table teacher(id int,name varchar(10)) engine=MyISAM;  
#指定存储引擎为MyISAM

MYSQL数据库--存储引擎_第10张图片

InnoDB行锁与索引的关系

一、简介

数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。对于任何一种数据库来说都需要有相应的锁定机制,所以MySQL自然也不能例外。MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应用场景特点都不太一样,为了满足各自特定应用场景的需求,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。MySQL各存储引擎使用了三种类型(级别)的锁定机制:表级锁定,行级锁定和页级锁定。

二、行级锁

行级锁定最大的特点就是锁定对象的颗粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。
使用行级锁定的主要是InnoDB存储引擎。

三、表级锁

通常用在DDL语句中,如DELETE TABLE,ALTER TABLE等。

和行级锁定相反,表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。
当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。

四、页级锁

页级锁定是MySQL中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。
在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
使用页级锁定的主要是BerkeleyDB存储引擎。

五、特性

表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
适用:从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。

行级锁定与表级锁定

准备一个数据表www:

create table www(id int primary key,name char(10),age int);

insert into www values(1,‘a’,100),(2,‘b’,200),(3,‘c’,300),(4,‘d’,400),(5,‘e’,500),(6,‘f’,600);
alter table www add index name_index(name);  
#对name字段创建普通索引

MYSQL数据库--存储引擎_第11张图片

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

  • delete from www where id=1;

因为id字段是主键,Innodb对于主键使用了聚簇索引,删除过程中会直接锁住整行记录。行级锁定。

  • delete from www where name=‘a’;

因为name字段是普通索引,会先锁住索引的两行(因为a有两行),接着会锁住相应主键对应的记录。行级锁定。

  • delete from www where age=100;

因为age字段没有索引,会使用全表扫描过滤,这时表上的各个记录都将加上锁。表级锁定。

死锁

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

session1 session2
begin; begin;
delete from www where id=5;#事务结束前,id=5的行会被锁定
select * from www where id=1 for update; #加排他锁,模拟并发情况,锁定id=1的行
delete from www where id=1; #死锁产生
update www set name=‘g’ where id=5; #死锁产生。因为会话1中id=5的行还在删除过程中,该行已被锁定
rollback; #回滚,结束事务。id=5的行被解锁
update www set name=‘g’ where id=5; #成功更新数据

for update: 可以为数据库中的行上一个排它锁。当一个事务的操作未完成时,其他事务可以读取该行数据,但是不能写入、更新或删除。

死锁演示:

MYSQL数据库--存储引擎_第12张图片

MYSQL数据库--存储引擎_第13张图片

MYSQL数据库--存储引擎_第14张图片

MYSQL数据库--存储引擎_第15张图片

MYSQL数据库--存储引擎_第16张图片

如何尽可能避免死锁

  1. 使用更合理的业务逻辑,以固定的顺序访问表和行。

  2. 大事务拆小。大事务更倾向于死锁,如果业务允许,将大事务拆小。

  3. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。

  4. 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从RR调整为RC,可以避免掉很多因为gap锁造成的死锁。

  5. 为表添加合理的索引。如果不使用索引将会为表的每一行记录添加上锁,死锁的概率大大增加。

概述:

  • MyISAM和InnoDB的区别:
  1. MyISAM:不支持事务和外键约束,占用空间较小,访问速度快,表级锁定,适用于不需要事务处理、单独写入或查询的应用场景。(写入和查询不一起使用的场景)
  2. InnoDB:支持事务处理、外键约束、占用空间比MyISAM 大,支持行级锁定,读写开发能力较好,适用于需要事务处理、读写频繁的应用场景。
  • 查看系统支持的存储引擎:
    show engines;
  • 查看表使用的存储引擎:
  1. 方法一:show table status from 库名 where name=‘表名’\G
  2. 方法二:show create table 表名;
  • 修改存储引擎:
  1. 方法一:修改已存在的表使用的存储引擎
    alter table 表名 engine=存储引擎名称;
  2. 方法二:修改配置文件,指定默认存储引擎
    vim /etc/my.cnf
    [mysqld]
    default-storage-engine=InnoDB #修改这一行,指定默认存储引擎为InnoDB
    systemctl restart mysqld #重启服务
  3. 方法三:创建表时指定存储引擎
    create table 表名(字段1 数据类型,…) engine=存储引擎名称;

如何选择合适的存储引擎
使用哪种引擎需要根据需求灵活选择,一个数据库中多个表可以使用不同的引擎以满足各种性能和实际需求。 使用合适的存储引擎,将会提高整个数据库的性能。 下面提供几个选择标准,然后按照标准,根据实际情况,选择对应的存储引擎即可:

  • 是否需要支持事务;
  • 是否需要使用热备;
  • 崩溃恢复,能否接受崩溃;
  • 是否需要外键支持;
  • 存储的限制;
  • 对索引和缓存的支持。

你可能感兴趣的:(数据库,mysql,服务器,java,开发语言)