【MySQL】-事务以及隔离性问题

时间:2022-12-23 11:55:11

作者:学Java的冬瓜
博客主页:☀冬瓜的主页????
专栏【MySQL】
分享:落霞与孤鹜齐飞,秋水共长天一色。——《滕王阁序》
主要内容:事务的概念,代码使用,事务的四大性质、隔离程度带来的问题,脏读、不可重复读、幻读,以及解决这些问题。

【MySQL】-事务以及隔离性问题
【MySQL】-事务以及隔离性问题
【MySQL】-事务以及隔离性问题

一、事务

1、什么是事务?

概念:

事务:指的是逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。

2、事务的使用

begin/start transaction  -- 开启事务

执行多个SQL语句

commit;   --提交  
--(开启事务后,中间的这些SQL不会立即执行,而是先等着,
--等commit后再全部执行,保证了事务的原子性)

rollback  -- 回滚

二、事务的性质(ACDI)

1、原子性(Atomic)

原子性:把各个单元组成逻辑上的操作,这组操作要么全部成功,要么全部失败。这个组合成一个整体的过程就叫做原子性。
因为原子代表不可切分的最小单位,所以原子性代表事务不能分开,事务是一个整体。

2、一致性(Consist)

一致性:事务执行前后,数据都是合法状态。比如转账,转出账号减1000,转入账号就得加1000,保持一致。一致性依赖原子性实现。

3、持久性(Durable)

持久性:事务会把执行的过程先记录到硬盘上,再执行要进行的操作。
若发生断电等不可控情况,这些数据不会丢失,等下次设备正常时,mysql感知到上次执行到的中间状态,然后根据之前记录的过程进行回滚。

4、隔离性(Isolated)-重点难点

隔离性:一个数据库服务器,同时执行多个线程的时候,事务之间的"相互影响程度"。

三、隔离性的深度剖析

1、隔离与并发的关系

  • 要理解的一个重点:隔离程度越高,意味着事务之间并发程度越低,执行效率越慢,但是数据的准确性越高。 相反地,隔离程度越低,事务之间并发程度越高,执行效率越高,但是数据的准确性越低。
  • 因此,要选择效率还是准确性,要看具体的业务。比如CSDN点赞功能,不需要赞数特别精确,而要做到块,所以可以选择隔离程度低,从而使并发程度高,提高效率;而对于银行业务需要准确性,所以要做到隔离程度高,从而使数据的准确性高。

2、隔离级别

@ (Read uncommitted)=》脏读

例子:

场景一:
当物理老师周老师在备课的时侯(事务1),他的学生小明凑过来看老师写了什么(事务2),小明看到周老师老师给了一道关于天体运动的物理题,小明就离开了,然后回家自学天体运动的题。然而在小明走后周老师改变了主意,把天体运动问题,改成了一道动能定理的题。

分析:

  • 脏读指事务1在写数据的同时,事务2在读数据,也就是说写的数据还没提交,但是事务2读取到了,就叫做脏读
  • 在场景一中,周老师备课还没完成(相当于提交数据),小明就在一边看到了数据,造成最终小明看到的和课堂上讲的内容不一样。所以造成了脏读。也就是说,写的同时读,并且数据还没提交,可能会造成脏读问题。
  • 用read uncommitted 作为隔离条件,会出现脏读问题
  • 解决脏读问题的方法,就是在周老师备课的时候,小明不能看,把办公室锁上(手动狗头),也就是周老师完全备课完,小明才能翻看备课本,就是给写"加锁"。即写数据的事务1要把数据提交过后,事务2才能读取数据,就用到更深一层隔离read committed(提交后读)。

@ (Read committed)=》不可重复读

例子:

场景二:
Java老师李老师发现自己提交到git的代码有部分错误,所以李老师就在这时修改了代码并重新提交到git, 与此同时,小明正在看老师的代码,然而小明看到一半代码后,代码就改变了,小明陷入了沉思…

分析:

  • 不可重复读,是事务1在读数据的时候,事务2在修改事务1正在读的数据,事务2提交修改后,事务1看到的数据内容就变了。
  • 在场景二中,小明、在读git代码的同时,李老师把代码修改了,造成小明读代码读到一半,代码就改变了。就是说读的同时写,然后写提交数据后,读发生了改变,就是不可重复读问题。
  • 以read committed作为隔离等级,会出现不可重复读问题。
  • 解决不可重复读的办法,就是小明在读代码时,李老师不能改代码,就可以避免不可重复读的问题,也就是给读加"加锁"。即事务1在读取数据时,事务2不能修改数据,用到的更深一层隔离是Repeatable read(可重复读)

@ (Repeatable read)=》幻读

分析:

  • 幻读,就是事务1在读文件1的同时,因为用来Repeatable read,事务2不能修改文件1,但事务二可以对其它文件操作,比如加个文件2,这就是幻读。
  • 在场景二中,用了Repeatable read给读"加锁"后,Java老师李老师不能再修改(操作)小明正在读的文件了,但是李老师还可以操作其它文件,比如添加其他文件,这样小明在读当前Java文件时,会看到多出来一个文件。所以就出现了幻读问题。
  • 解决幻读问题方法,除了给当前文件的读和写"加锁",同时文件列表也"加锁"。就可以解决幻读问题了。这就用到了更深一层隔离,Serializable(串行化)

@ (Serializable)

  • 进一步解决了幻读问题,但是彻底放弃并发

3、 隔离级别总结

  • Read uncommitted,隔离级别最低,会发生脏读、不可重复读、幻读问题。数据准确性低;但是并发程度高,执行效率快
  • Read committed,对写"加锁"。隔离级别提高,解决了脏读问题,会发生不可重复读、幻读问题。数据准确性比第一个高,但整体来说准确性还是较低;并发程度比第一个低,效率减慢。
  • Repeatable read,对读和写"加锁"。隔离级别进一步提高,解决了脏读,不可重复读问题,会发生幻读问题。准确性较高;并发程度比第二个低,效率进一步减慢。
  • Serializable,对读和写"加锁",包括列表所有文件按。隔离级别最高,解决了脏读、不可重复读、幻读问题。彻底舍弃并发,效率最低。
  • 在MySQL中,Repeatable read 为默认隔离级别(可修改),也就是解决了脏读、不可重复读,不管幻读问题。