Mysql的事务与锁之间的关系 您所在的位置:网站首页 什么是事务什么是锁 Mysql的事务与锁之间的关系

Mysql的事务与锁之间的关系

2024-07-09 20:04| 来源: 网络整理| 查看: 265

一.事务:ACID

如转账业务: A – B 1000 A -1000 B +1000

二.事务并发引起的问题 ·脏读不可重复读幻读 隔离级别:

读未提交 (脏读,不可重复读,幻读)这个级别对数据是没有加锁的,就是最低的级别的

读已提交 就是事务A只能读取到事务B提交后的数据,如果B没提交,A读取到的是之前的数据,而不是B修改后的数据。

可以去除脏读(没提交的数据是读不到的)了 (不可重复读,幻读)

不可重复读: 如A读到数据 a=100,此时B修改a=120提交了(未提交A读到的还是a=100),A再查询就变成120了,这样就是不可重复读了。就是A还在同一个事务中对a的两次读取到的数据不一致了。

可重复读(mysql默认的) **就是A还在同一个事务中对a的两次读取到的数据一致。**无论其他事务是否对a进行了修改是否提交了,都不影响到A事务。(幻读),但是Mysql不一样,有Next-Key锁保证不出现幻读。Next-Key = X锁+间隙锁

串行化 若A先开始事务,那么其他事务可以进行查的操作,但是不可以进行update,insert和delete操作。执行会被锁住。

innodb锁的原理解析

1.共享锁

select....from table where...lock in share mode S锁,读锁(A获得了a的共享锁,则B就不能对a进行修改,但可以进行查询,除非A事务提交了)

2.排他锁

select…for update X锁,写锁(A获得了a排他锁,其他事务不能对a进行加任何锁)

注意:如果我们是根据id=1对数据进行修改的话,那mysql只会对id=1这一行进行加锁(行级锁),但是如果我们是根据其他字段定位而对数据进行修改的话,mysql会对整个表进行加锁(表锁)。除非我们把这个字段定义为唯一索引。

innodb行锁,锁的是什么? 注意:行锁就是给索引上的索引项加锁,也就是说,我们只有是通过索引对数据进行检索的时候,innobd才会对数据加行级锁,否则就会使用表锁。因为没有索引嘛,那innodb就只能全表扫描了,这时候就只能加表锁了。

其实就是优化锁之间的性能的。 3.意向共享锁

IS,事务要先获取到一个数据的共享锁之前,要先获取到意向共享锁

4.意向排他锁

IX,事务要先获取到一个数据的排他锁之前,要先获取到意向排他锁

5.自增锁

就是针对主键id来说的,就是我们插入数据时,就算没有提交(回滚了),这些id也会丢失掉。

我们进行范围查询才会用到 6.临键锁 如果我们是采用> < between这种范围查询的话,就是为了解决幻读的问题的。(左开右闭)就是区间加锁 这个结果是有的,就是有匹配记录,那么在对应的范围内加上临键锁,其他事务就不能对这范围内的进行操作了。 7.间隙锁 没有匹配记录,临键锁会降级为间隙锁(快照读) 8.记录锁

精准匹配的,范围匹配的,范围匹配没结果的,有各种锁

脏读就是用排他锁解决不可重复读 共享锁幻读是通过间隙锁或临键锁

mysql是通过MVCC+Next-key lock解决幻读

MVCC

使用锁控制并发时,只要是写数据的任务没有完成,数据就不可以被其他的任务获取,就连读数据的select操作也会阻塞,这对并发度要求较大的环境有很大的影响,为了解决这个问题引出了数据多版本。 数据多版本实现的原理是:

1,写任务发生时,首先复制一份旧数据,以版本号区分

2,写任务操作新克隆的数据,直至提交

3,并发读的任务可以继续从旧数据(快照)读取数据,不至于堵塞

排它锁 是 串行执行 共享锁 是 读读并发 数据多版本 是 读写并发

总结

我们知道 Mysql有四个特性:ACID,A就是原子性,C就是一致性,I就是隔离性,D就是持久性。 那对于持久性Mysql是通过redo log来实现的,redo log就是重做日志,而undo log就是回滚日志,主要是用来保证原子性的,而对于隔离性的话,则是通过锁机制和MVCC来保证的,隔离的话就保证了最终数据的一致性了。

首先数据库锁的实现方式有两种嘛 1.悲观锁(共享锁,排他锁,意向共享锁,意向排他锁,临键锁,间隙锁,记录锁) 我们在进行写操作的时候,默认都是加排他锁的,像update,select,delete操作 2.乐观锁(其实就是不加锁,用MVCC来实现乐观锁)

按锁的粒度又分为行锁和表锁和间隙锁 行锁就是如果我们通过索引来检索数据的话,那它才会对索引上的索引项进行加锁,这个锁就是行锁 而如果我们只是对通过普通字段进行检索的话,那就会对其加上表锁,因为不是精确匹配嘛。 间隙锁就是两者之间的折中了,就是对一个范围进行加锁,间隙锁主要是用来解决幻读的。

通过加锁的方式可以保证数据的一致性,但是对一同一条数据,我们只能进行并发读,不能读写并发,所以这个时候就引入了乐观锁这个机制,也就是MVCC

MVCC实现的原理其实就是在进行写操作的时候,数据库会先复制一份旧的数据,然后它是按版号来进行区分,因为在数据库中的每一张表其实是冗余了两个字段,一个字段是数据创建的版本号,一个是数据过期的版本号,每一个事务都有对应的一个事务id这样,写操作就只操作新克隆出来的数据,直至事务提交,而其他事务的并发读的数据就是旧数据,所以MVCC就支持读写并发了。

然后谈一下事务的持久性吧, 因为事务的持久性是透过redo log来实现的嘛,首先我们知道,内存中的数据刷新到磁盘的时间其实是随机性的嘛,那这样的话效率就很低了,于是数据库就就在两者之间加入了一个redo log,就是我们的数据先写在redo log上,然后再讲redo log刷新到磁盘上。 假如我们的数据库宕机了,那么重启时,redo log中的数据就会重新刷新到磁盘上,这样就保证了持久性。redo的作用是为了保障已提交事务的ACID特性,也就是保证了数据的D(Durability)持久性。

再聊一下事务的原子性。 事务的原子性是通过undo log来实现的,数据库修改数据未提交的时,他会讲修改数据前的旧数据存到undo log上,当事务回滚或出事时,会从日志获取旧数据,避免未提交数据对数据库的影响。undo的作用是为了保障未提交的事务不会对数据库的ACID产生影响。也就是保证了操作的A(Atomicity)原子性。

还有一个需要注意的地方就是Innodb所有的普通select都是快照读,快照读不加锁,这也是innodb支持高并发的原因之一。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有