MySQl之存储引擎

一.关于存储引擎概念介绍

1.存储引擎概念介绍

  • 存储引擎 是MySQL数据库中的组件,负责执行实际的数据I/O操作,工作在文件系统之上,数据库的数据会先传输到存储引擎,会按照存储引擎的格式保存到文件系统中

2.MySQL常用的存储引擎

  • MyISAM:不支持事务、外键约束,只支持表级锁定,适合单独的查询或插入操作,读写并发能力较弱,支持全文索引,资源占用较小,数据文件(.MYD)和索引文件(.MYI)是分开存储的。适用于不需要事务处理,单独的查询或者插入数据的业务场景

  • InnoDB:支持事务、外键约束,支持行级锁定(在全表扫描时仍然会表级锁定),读写并发能力较好,支持全文索引(5.5版本以后的),缓存能力较好可以减少磁盘IO的压力,数据文件也是索引文件。适用于需要事务的支持,一致性要求较高,数据会频繁更新,高并发读写的业务场景

二.MyISAM 介绍

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

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

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

  • 压缩表:压缩表由 myisamchk 工具创建,占据非常小的空间,因为每条记录都是被单独压缩的,所以只有非常小的访问开支

2.MyISAM适用的生产场景

  • 公司业务不需要事务的支持

  • 单方面读取或写入数据比较多的业务

  • MyISAM存储引擎数据读写都比较频繁场景不适合

  • 使用读写并发访问相对较低的业务

  • 数据修改相对较少的业务

  • 对数据业务一致性要求不是非常高的业务

  • 服务器硬件资源相对比较差

  • 总结:MyIsam:适合于单方向的任务场景、同时并发量不高、对于事务要求不高的场景

3.InnoDB 特点介绍

  • 支持事务,支持4个事务隔离级别

  • MySQL从5.5.5版本开始,默认的存储引擎为InnoDB

  • 读写阻塞与事务隔离级别相关

  • 能非常高效的缓存索引和数据

  • 表与主键以簇的方式存储

  • 支持分区、表空间,类似oracle数据库

  • 支持外键约束,5.5前不支持全文索引,5.5后支持全文索引

  • 对硬件资源要求还是比较高的场合

  • 行级锁定,但是全表扫描仍然会是表级锁定(update table set a=1 where user like ‘%zhang%’;)

  • InnoDB 中不保存表的行数,如select count() from table;时,InnoDB需要扫描一遍整个表来计算有多少行,但是MyISAM 只要简单的读出保存好的行数即可。需要注意的是,当count()语句包含where条件时 MyISAM 也需要扫描整个表

  • 对于自增长的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中可以和其他字段一起建立组合索引

  • 清空整个表时,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表

4.InnoDB适用生产场景分析

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

 四 .存储引擎命令

  • 查看系统支持的存储引擎
show engines;
例:mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

| Engine | Support | Comment | Transactions | XA   | Savepoints |
| ------ | ------- | ------- | ------------ | ---- | ---------- |
|        |         |         |              |      |            |

+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

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

+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec)
  • 查看表使用的存储引擎
方法1:show table status from 库名 where name='表名'\G
方法2:use 库名;
show create table 表名;
例:mysql> use tour;

Database changed

mysql> show create table moon;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                      |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| moon  | CREATE TABLE "moon" (
  "id" int(11) DEFAULT NULL,
  "name" char(4) DEFAULT NULL,
  "age" int(11) DEFAULT NULL,
  "sex" char(2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
  • 修改存储引擎

① 通过 alter table 修改

use 库名;
alter table 表名 engine=MyISAM;

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

vim /etc/my.cnf
......
[mysqld]
......
default-storage-engine=INNODB
systemctl restart mysql.service

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

use 库名;
create table 表名(字段1 数据类型,...) engine=MyISAM;

1.MyISAM和InnoDB的特点

  • MyISAM :默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。不是事务安全的,而且不支持外键,如果执行大量的select,insert MyISAM比较适合

  • InnoDB :支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。注: 在MySQL 5.5之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,
    默认的搜索引擎变更为InnoDB

2.MyISAM和InnoDB的区别

  • InnoDB支持事务,MyISAM不支持。对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务
  • InnoDB支持外键,而MyISAM不支持。InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高
  • MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针
  • 主键索引和辅助索引是独立的
  • InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快
  • InnoDB不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;5.7以后的InnoDB支持全文索引了
  • InnoDB支持表、行级锁(默认),而MyISAM支持表级锁
  • InnoDB表必须有主键(用户没有指定的话会自己找或生产一个主键),而Myisam可以没有
  • InnoDB存储文件有frm、ibd,而Myisam是frm、MYD、MYI
  • InnoDB:frm是表定义文件,ibd是数据文件。Myisam:frm是表定义文件,myd是数据文件,myi是索引文件

四. InnoDB行锁与索引的关系

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

1.如果id字段是主键,innodb对于主键使用了聚簇索引,会直接锁住整行记录

delete from t1 where id=1;	

2.如果name字段是普通索引,会先锁住索引的两行,接着会锁住相应主键对应的记录

delete from t1 where name='aaa';  

3.如果age字段没有索引,会使用全表扫描过滤,这时表上的各个记录都将加上锁

delete from t1 where age=23;

五.死锁

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

  • 案例
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  #分主机1								
begin;								
delete from t1 where id=5;										
session 2  #分主机2
begin;
select * from t1 where id=1 for update;
session 1  #分主机1
delete from t1 where id=1; #死锁发生
session 2  #分主机2
update t1 set name='abc' where id=5; #死锁发生
  • for update 可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新
  • 共享锁:又叫做读锁,当用户要进行数据的读取时,对数据加上共享锁,共享锁可以同时加上多个
  • 排他锁:又叫做写锁,当用户要进行数据的写入时,对数据加上排他锁,排他锁只可以加一个,它和其它的排他锁,共享锁都相斥

2.如何尽可能避免死锁?

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

六.总结

  • 索引:加速——>便于客户端获取数据(提升用户体验感)+ 减少mysql 服务器的压力。

你可能感兴趣的:(MYSQL,mysql,数据库,java)