MySQL会用,但是对于那些引擎与锁总是迷卜楞登的,所以今天时机正好就整理一下
(看了一篇文章 觉得自己好像懂了--多多捂脸)如有错误,还请不吝赐教,感恩 ♥
1. 文章开头先来说下MySQL是什么 (虽然都知道 还是顺序罗嗦一下)
MySQL是一个**关系型数据库**管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下产品。
MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件
2.MySQL 引擎
2.1 MyISAM存储引擎
- 不支持事务
- 不支持外键
- 只支持表锁
- 访问速度快
- 对事务完整性没有要求,要求以select \ insert 为主的 应用基本上可以用这个引擎来创建表
2.2 InnoDB 存储引擎 // MySQL默认 存储引擎
- 支持事务
- 支持外键
- 支持行锁和表锁
MEMORY 存储引擎
- 查询快
- 存在内存,会随时丢失,
- 支持散列索引 和B树索引
- 散列索引 ‘相等比较’ 时非常快,但对‘范围比较’ 速度就慢了,因此散列索引值 适合使用在和操作符,不适合或操作符,也同样不适合在order by 子句中使用
Archive存储引擎
- 适合存储归档数据,如日志信息,
- 只支持insert 和select 操作 其设计的目的是提供告诉的插入和压缩功能。
2. MySQL 索引
打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。
-
提高MySQL的检索速度
-
索引分为单列索引 和 组合索引 即一个索引只包含单个列,一个列可以有多个单列索引,但这不是组合索引 。组合索引 即一个索引包含多个列。
-
索引会提高查询速度,同事会降低更新表的速度,如对表进行 insert update delete 。因为更新表的时候不仅要保存数据,还要保存一下索引文件。
-
建立索引 会占用磁盘空间的索引文件。
创建索引 :
-
普通索引
-
ALTER table tableName ADD INDEX indexName(columnName)
-
唯一索引
-
CREATE UNIQUE INDEX indexName ON mytable(username(length))
正题
1. InnoDB 存储引擎
- 使用InnoDB 的两大优点 : 一是支持事务,二是支持行锁
2 MySQL事务
在高并发的情况下事务的并发处理会带来的几个问题
- 脏读
- 事务A 处理过程中读取到了事务B未提交的数据。
- 不可重复读
- 一个事务执行的过程中 多次查询某一数据的时候结果不一致的现象,由于在执行过成功被另一个事务修改了数据并提交了事务。
- 幻读
- 对一批数据的操作完成后,在其他事务有插入了满足条件的数据 导致的现象。
3.由于高并发事务带来的这几个问题,所以就产生了事务的隔离界别
- Read uncommitted (读未提交) :最低级别,任何情况都无法保证
- Read committed (读已提交) :可避免脏读的发生。
- Repeatable read (可重复读):可避免脏读,不可重复读的发生。
- Serializable (串行化) :可避免脏读, 不可重复读,幻读 。
4. InnoDB 常见的几种锁机制
- 共享锁和独占锁
InnoDB 通过共享锁和独占锁两种方法实现了标准的行锁。
共享锁: 允许事务获得锁后去读数据。
独占锁:允许事务获得锁后去更新或者删除数据,
一个事务 获得共享锁后,允许其他事务获取共享锁,
此时两个事务都持有共享锁,但是不允许其他事务获取独占锁。
如果一个事务获取独占锁 则不允许其他事务获取共享锁或者独占锁,必须等到该事务释放锁后才可以获取到。
- 意向锁
上面说过的InnoDB 支持行锁和表锁,意向锁是一种表级锁,用来只是接下来一个事务将要获取什么类型的锁(共享还是独占)
意向锁 分为 意向共享锁(IS) 和意向独占锁 (IX),
以此表示接下来是获取共享锁还是独占锁。
意向锁不需要显示的获取,在我们获取共享锁或者独占锁的时候会自动获取,意思也就是说,如果要获取共享锁或者独占锁,
则一定是先获取到了意向共享锁或者意向独占锁,
意向锁不会锁住任何东西,除非有进行全表请求的操作,否则不会锁住任何的数据,
存在的意义只是用来表示有事务正在锁某一行的数据,或者将要锁某一行的数据。
- 记录锁
锁住某一行 如果表存在索引,那么记录锁是锁在索引上的,
如果表没有索引,那么InnoDB 会创建一个隐藏的聚簇索引加锁,
所以我们在查询的时候尽量采用索引进行查询,这样可以降低锁的冲突
-
间隙锁
- 间隙锁是一种记录行与记录行之间存在空隙或者在第一行记录之前或在最后一行记录之后产生的锁,间隙锁可能占据的单行,多行或者空记录,
通常的情况是我们采用范围查找的时候,比如在学生成绩管理系统中,如果此时有学生成绩 60,72,80,95,一个老师要查下成绩大于 72 的所有同学的信息,采用的语句是 select * from student where grade > 72 for update,这个时候 InnoDB 锁住的不仅是 80,95,而是所有在 72-80,80-95,以及 95 以上的所有记录。为什么会 这样呢?实际上是因为如果不锁住这些行,那么如果另一个事务在此时插入了一条分数大于 72 的记录,那会导致第一次的事务两次查询的结果不一样,出现了幻读。所以为了在满足事务隔离级别的情况下需要锁住所有满足条件的行。
- 间隙锁是一种记录行与记录行之间存在空隙或者在第一行记录之前或在最后一行记录之后产生的锁,间隙锁可能占据的单行,多行或者空记录,
-
NK (记录锁和间隙锁的组合锁)
- Next-Key Locks,NK 是一种记录锁和间隙锁的组合锁。是 2 和 3 的组合形式,既锁住行也锁住间隙。并且采用的左开右闭的原则。InnoDB 对于查询都是采用这种锁的。
-
乐观锁
- 乐观锁,大多是基于数据版本( Version )记录机制实现。 何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对, 如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
-
悲观锁
- 悲观锁就是当我们去获取数据的时候,不论我们有没有打算去修改,悲观锁都会认为我们一定会去修改这个数据,所以 他会把这个数据直接锁死,其他的人想操作操作,那你就阻塞,直到轮到你获取锁为止。
乐观锁和悲观锁的区别
8. 乐观锁 总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。
- 悲观锁总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起
本文参考: https://mp.weixin.qq.com/s/JHrlyOIFgjWtZKgjRKYr-g
本文参考:https://mp.weixin.qq.com/s/Oe_NzPAL7OazlR4m56trvQ