引言
作为一名程序员,数据库是我们日常工作和学习中最常用到的数据存储与交互软件,而数据库又可以分为很多种,今天所说的是最常见也是最常用的数据库MySQL,它是一种基于硬盘存储的关系型数据库,而学习数据库,我们就不得不去了解一个知识点,那就是数据库事务,今天我们就基于MySQL数据库,讲一讲它的事务并发隔离级别。
事务
一、什么是事务?
事务是数据库操作的做小工作单位,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元);
二、事务的四大特性
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各个操作要么都做,要么都不做,也就是说一个事务可以看成一个原子,原子是不可再分割的。
2 、一致性
事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
事务并发安全问题
一、脏读
脏读指的就是脏数据,一个事务并未提交的数据便是脏数据。
二、不可重复读
一个事务在执行期间无论重复读取多少次数据,返回的结果都应该与第一次读取到的数据一致,如果不一致,那便意味着发生了不可重复读的安全问题。
三、幻读
幻读侧重的是整行的数据变化,如果一个事务在执行期间读取到的结果数量不相同,那就说明读取到了幻影数据,发生了幻读问题。
事务隔离级别
了解了什么是事务之后,接下来就进入到今天这篇文章的正题了,那就是事务的第三大特性——隔离性,而隔离性又分为四个不同的隔离级别,之所以会分为不同的隔离级别,是因为不同的隔离级别对事务的隔离强度是不一样的,所有就会导致数据库在各个事务隔离级别下的性能大有不同,在日常工作中我们要根据工作的具体内容来选择合适的事务隔离级别,万万不可一步到位直接选择最强的隔离级别。
一、READ-UNCOMMITTED
顾名思义,读未提交,一个事务能读取到另一个事务还未提交的数据,也就是脏数据。
1、首先我们用MySQL可视化工具开启两个查询来模仿两个事务并将他们各自的隔离级别设置为READ-UNCOMMITTED,然后在每个查询中各开启一个事务,然后在session1查询一次表数据。
我们主要针对id=1的数据项的balance属性值进行操作,可以看到现在balance的值为1000,现在我们将balance的值改为1111但是并不提交,然后在session2中查询,可以看到session2中已经可以查到id=1的数据项的balance值为1111,然而我们并未提交session1的修改,这时session2中读取的数据为session1并未提交的数据,也叫做脏数据。
二、READ-COMMITTED
为了防止读取到未提交的脏数据,这时就需要用到MySQL的第二种事务隔离级别-READ-COMMITTED,也叫做读已提交,首先我们将两个session的事务隔离级别设置成READ-COMMITTED,重复上述的操作我们可以发现,session2已经不能读取到session1中还未提交的数据了,所以READ-COMMITTED事务隔离级别防止了脏数据的读取。但是它还是不完美的,它并不能防止每次读取到不一样的数据。首先我们开启两个session的事务,并在session2中读取一次id=1的数据项balance属性的值。
可以看到balance的值为1000,这时我们在session1中将id=1的数据项的balance属性值更改为2222,并提交,然后在session2中再次读取一次id=1的balance值,发现balance=2222,可是根据事务的隔离性,一个事务从始至终的无论重复查询多少次都应该查到同一个结果,所以读已提交这种事务隔离级别也并不是完美的,这时就出现了第三种事务隔离级别,可重复读。
在当前事务隔离级别下和第一种事务隔离级别下,还会出现一种事务并发安全问题,那就是幻读,幻读侧重的是整行数据项的变化。我们先开启两个session的事务,然后在session2中读取一下全表数据,然后在session1中添加一条数据并提交。
然后我们在session2中再次读取全表数据,发现我们竟然读取到了session1中添加的那条数据,可是session2一直在自己的事务中操作而且没有提交过,这时读取到的session1中插入的数据叫做幻影数据。
在MySQL5.7之前第三种事务隔离级别——重复读也并不能防止这种情况的发生,只能使用最后一种事务隔离级别——串行读,顾名思义,它限制MySQL单线程访问,所以就不存在并发的情况,自然而然就没有了事务安全问题,但是缺点是效率太低,MySQL团队也是get到了这一点,所以在MySQL5.7开始在重复读的隔离级别下就解决了所有并发安全问题,就不需要用到串行读了,笔者的MySQL也是在前段时间升级到了5.7,所以就将幻读在第二种事务隔离级别下演示了。
三、REPEATABLE-READ
可重复读,上面已经说过,在MySQL5.7开始,重复读隔离级别便可以解决所有并发安全问题,在这就不再多说了。
四、SERIALIZABLE
这就是单线程的串行读,效率太低,现在也是被抛弃了,可重复读隔离级别便可以满足你所有的需求了。
事务隔离级别与事务并发安全问题关系表
文章不长,如果大家想要具体操作视频的话可以关注私信我。