mysql数据库的锁机制及事务特性

MyISAM和InnoDB关于锁方面的区别


首先我们来了解一下表锁行锁

MyISAM默认用表级锁,不支持行级锁
表级锁分为共享表锁(读锁)排他表锁(写锁)
当先执行某个语句时,会默认先上锁,有先后顺序,
1、当select将会加上读锁(在末尾加上for table也可以加上写锁)
2、update,insert,delete操作时会上写锁
3、lock tables 表名 read(write) 上读(写)锁


读锁时,同为读锁的操作也可以进行,而写锁操作不能进行
写锁时,同为写锁的操作也不可以进行,读锁行为也无法操作。

InnoDB支持行锁和表锁默认使用行锁,与MyISAM区别在于:

1、InnoDB只有通过索引条件检索数据才使用行级锁,否则,InnoDB将使用表锁(它的行锁基于索引

2、MyISAM可以支持查询和插入操作的并发进行。可以通过系统变量 concurrent_insert来指定哪种模式,它默认,如果MyISAM表中表的中间没有有被删除的行,那MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。
但是InnoDB引擎是不支持的!

MyISAM与InnoDB适用场景

MyISAM
1、MyISAM适合频繁执行全表count(因为MyISAM有自带行数记录,InnoDB没有)
2、MyISAM适合对增删改的频率不高的数据,查询(select)频繁的(因为聚集索引+MVCC+事务所需要的维护比MyISAM多太多了

InnoDB
1、更适合增删改查频率高的数据(行锁只会锁操作行的值,而不是整张表)
2、安全性,可靠性要求高的数据(支持MVCC+事务

事务的四大特性


事务的四大特性简称ACID,分别是:
1、原子性(Atomic)用户包含的全部操作,要么一起操作,要么不操作
2、一致性(Consistency)应满足完整性约束
3、隔离性(Isolation)一个事务的执行不应该影响其他事务
4、持久性(Durability)保持数据永久修改

事务隔离级别对并发访问的影响以及MVCC


事务可以避免并发引起的问题,如:
更新丢失---Mysql已经可避免

脏读---一个事务读到另一个事务未提交(commit)的数据

不可重复读---一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。但是两次执行同样的查询,可能会得到不一样的结果。

幻读---并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在准备插入此记录,但执行 insert 时发现此记录已存在无法插入,此时就发生了幻读

关于幻读的理解,详情请参考https://segmentfault.com/a/1190000016566788
而隔离级别的解决方案,如下图

RR(可重复读)情况下使用MVCC(多版本并发控制)避免幻读


我们先来科普下当前读快照读

当前读:没什么好说的,其实就是前面所说的给语句加上读锁和写锁

快照读:就是非阻塞读,不加锁的select就是快照读

在表锁中我们读写是阻塞的,基于提升并发性能的考虑MVCC一般读写是不阻塞的(所以说MVCC很多情况下避免了加锁的操作)

MVCC实现的读写不阻塞正如其名:多版本并发控制--->通过一定机制生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本。

简单地说就是(如上图):当session1进行了一次select之后,session2进行了update修改了fieled3,那么undo日志会将语句会存入一个数据快照用于回滚,而session1再调用select语句的时候会创建一个read view(用来决定查看快照数据还是最新数据),查询的其实是快照数据,而非最新数据

间隙锁GAP


其实RR防止幻读本质是GAP

当我们用范围条件检索数据InnoDB引擎会给符合范围条件的已有数据记录的索引项加锁,一般我们称之为间隙锁(GAP)

!!间隙锁只会在 Repeatableread隔离级别下使用

对主键索引和唯一索引时,
where条件全部命中,则只会加记录锁
where条件未全部命中,就会加GAP锁

其他条件下,如:非唯一索引或者不走索引的当前读情况下
GAP锁无法精确定位范围

非唯一索引

它将会把指定位置的(6,9],(9,11]的区域锁定,根据叶子节点的顺序排列的值,如bd将会被上锁
不走索引

而不走索引的情况下,整张表将会被锁住

你可能感兴趣的:(mysql数据库的锁机制及事务特性)