存储引擎概念
在mysql当中数据库用不同的技术存储在文件中,每一种技术都是使用不同的存储引擎机制,索引技巧,锁定水平,以及最终提供的不同的功能和能力,这些就是我们说的存储引擎 |
主要功能
1 | mysql将数据存储在文件系统中的一种方式和格式 |
2 | 存储引擎负责执行实际的数据I/O操作 |
3 | 存储引擎介于数据和文件系统之间,数据会先保存到存储引擎,再按照存储引擎的格式保存到文件系统 |
Mysql的存储引擎分类
INNODB | 5.5版本之后的mysql默认存储引擎,也叫事务型速记引擎(写入性能较好),支持ACID(事务的四大特性),支持锁行,锁表。 |
MYISAM | 5.5之前的默认存储引擎,插入数据的性能较高,查询速度很优秀,但是不支持事务,也是他被淘汰的原因 |
Memor | 所有数据都保存在内存的存储引擎,插入数据,更新数据,查询数据,速度很快,但是占用内存空间比较大,会占用和数据量成正比的内存空间,而且mysql一旦重启,内容很快就会丢失 |
Csv | 由逗号分割数据的存储引擎,他会在数据库子目录里为每一个数据表创建一个 .CSV文件,他就是一种普通文本文件,每个数据占用一个文本行,但csv不支持索引 |
Archive | 非常适合存储大量的独立的,而且是历史数据的引擎,因为他不需要经常读取,插入的速度很快,只是查询的效率比较低 |
Blackhole | 黑洞引擎,写入的任何数据都会消失 |
MYISAM和INNODB做个分析和对比
MYISAM | 不支持事务,也不支持外键,只支持全文索引,数据文件和索引文件是分开的,访问速度快,适用于查询和插入为主的应用 |
.frm : 存储的表结构 .MYD:存储的数据文件 .MYI:索引文件 |
MYISAM的特点
1 | 表级锁定,更新数据时,整个都将锁定 |
2 | 数据库在读写过程中是相互阻塞的(即你不能对一个表又读又写) |
支持的存储格式
静态表 | 固定长度表,静态表时mysisam的默认存储格式,静态表中字段都是非可变字段,因此每个记录都是固定长度 |
优点 | 数据存储快,方便缓存,有了故障容易恢复 |
缺点 | 占用空间比较多 |
动态表 | 可以包含可变字段,记录的长度是不固定的 |
优点 | 占用空间比较少 |
缺点 | 频繁更新数据,删除记录,会产生碎片,需要定期清理(myisamchk -r : 清除命令),一旦出现故障恢复比较麻烦。 |
压缩表 | myisamchk 工具创建的,占据的空间非常小,每条记录都是单独压缩的 |
重点 INNODB
1 | 支持事务,支持4个隔离级别,5.5之后是mysql的默认存储引擎 |
2 | 读写阻塞和隔离级别相关 |
3 | 支持高效的缓存索引以及缓存数据 |
4 | 表于主键以簇方式存储BTREE |
5 | 支持外键约束,5.5之后INNODB也可以支持全文索引 |
6 | 对硬件资源的要求比较高 |
7 | 支持行锁,也可以支持表锁定(全表扫描) |
有几个注意点
1 | 如果使用like模糊查询,会进行全表扫描,并且送定整个表 |
2 | 对没有创建索引的字段进行增,删,改,也会进行全表扫描,锁定整个表,查询可以 |
3 | 使用索引进行查询,则是行级锁定 |
INNODB的特点
1 | 不保存表的行数,统计表的行数,会扫描一边整个表来计算有多少行 |
2 | 自增长索引,INNODB中必须包含只有该字段的索引 |
3 | Delete 定空表,它是一行一行删,速度比较 truncate |
使用场景
1 | 业务需要事物的支撑 |
2 | 论坛,微博,对数据一致性比较高的场景 |
3 | 访问量和并发量比较高的场景,INNODB支持缓存,可以减少后台服务器的压力 |
三个文件
1 | 表名.frm 表结构文件 |
2 | 表名.ibd 既是数据文件,也是索引文件 |
3 | db.opt 表的属性文件 |
Innodb行锁和索引的关系,以及表锁,排他锁,死锁
行锁 | 如果列名字段是一个普通索引,会锁住索引行,对应的主键一并锁住,实际上就是行锁 如果使用的id是主键,innodb对主键使用聚簇索引,锁定整行的记录 |
锁定表 | 要对一个非索引键进行操作,当一个事务对非索引列进行操作,因为要全表扫描过滤,所有整张表都会被锁定,另一个事务只能查 |
排他锁 | 一个事务在操作,另一个事务的操作无法执行,只能查,排他锁只能加一个 |
死锁 | 事务之间相互等待对方资源,最后形成一个环路造成的,使用for update 排他锁 可以形成死锁 发生死锁的时候,数据库会自动选择一个事务作为受害者,然后会先解锁死锁,再回滚事务 mysql的默认死锁机制,会中选择一个事务作为死锁的牺牲品,直接终止其中一个事务,但是不会自动回滚。 |
- 存储引擎只能innodb
- Mysql默认隔离级别即可
如何尽可能避免死锁
1 | 业务的逻辑要合理,以固定的顺序访问表和行 |
2 | 如果食物的类型比较复杂,要进行拆分,在业务允许的情况下,可以把大事务拆小,分次执行 |
3 | 在同一事务中,尽可能一次性锁定所有需要的资源,可以减少死锁的概率 |
4 | 隔离级别,如果要避免死锁,可以用read commit 可以避免索引 |
5 | 添加合理索引,可以减少死锁的概率 |
悲观锁
乐观锁:不会有任何提示,只是数据不能写入,数据提交更新时,他会进行校验,如发生冲突,最多也就数据不生效而已,没有其他报错,或卡顿卡停现象
一般来说,我们会在表中配置一个version字段,可以自增,通过自增校验来查看数据是否冲突
也可用时间戳方式
索引和行锁之间的关系
非索引的锁表以及死锁
排他锁(悲观锁)
Innodb的机制,和存储文件的格式