要想讲清楚数据库的事务隔离级别,首先得明白数据库事务是什么,每件东西的诞生必有它的用途。先看一个小故事。
生活中有这种常见的场景:银行的转账,A同学账户中有1000元,B同学账户中有2000。现在A同学需要转账给B同学300。而在数据库的层面上来讲,这包含两个操作:首先在A账户中减去300,A账户的钱变为700,然后在B账户中加上300,B账户的钱变成2300。
问题思考:假设在A同学转账完成后,此时系统崩溃,B账户还没有来得及加上300元,这显然是大家不能接收的结果。
事务则是将一系列的操作包装成为一个整体运算集合,这个运算集合要么都执行,要么都不执行。
所以,如果我们将这两个操作定义在一个事务中执行,那么很显然可以及时避免这种问题,即取款的这两个步骤要么都执行成功,要么都不执行。
一般来讲事务具备四个特性,简称ACID。
如果不考虑事务之间存在隔离性,在多个事务对同一张表进行操作时,将会产生数据的不一致性。一般来说可分为:脏读,不可重复读,幻读
在MySQL中创建一张student表,并且在表中插入三条数据
CREATE TABLE `student` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES ('1', '小明', '88');
INSERT INTO `student` VALUES ('2', '小红', '13');
INSERT INTO `student` VALUES ('3', '小李', '14');
说明,在MySQL中默认是开始事务自动提交功能,也就意味着,平常我们每执行一条SQL语句就进行了一次事务的提交,可以一下命令进行查看,结果为1表示启动事务自动提交功能。
SELECT @@autocommit;
当然可以不用理会这个变量,我们可以每次手动的开启事务与提交事务,当然也可以回滚事务。其命令分别如下所示
START TANSACTION;
COMMIT;
ROLLBACK;
当前有两个事务在访问同一个数据区时,A事务对数据进行了修改,而且这种数据修改还没有提交到数据库中,这时B事务刚好使用了这个被修改的数据。
session1未提交的修改直接被session2访问,造成脏读
事务之间交叉执行,导致在一个事务内,多次读同一数据,出现不同的结构。其原因是在B事务没有结束并且多次访问数据区dataQ,但是存在A,C,D等多个事务都修改了dataQ,修改提交后的结果都被B看到了。
session1未提交的修改,session2已经访问不到,避免了脏读。但是在session1提交了修改后,session2立刻可以访问到数据的修改。在session2的角度来说,在一次事务中针对同一个数据的两次读操作结果不同,结果是不可重复读。
事务不独立执行,则会发生幻读现象。在同一个事务提交前后查询的结果不一样,就像产生了幻觉了一样。
幻读演示如下
session1未提交的修改,session2已经访问不到,避免了脏读。并且session1提交了修改后,session2也不能访问到数据的修改。但是当session2提交本次事务后,在本次事务提交前后针对同一个数据的两次读操作结果不同,就像产生了幻觉一样,即幻读。
针对上述所说的事务并发执行所带来的不良影响,可以通过设置数据库事务隔离级别使这些不良的影响达到一个可控的范围。MySQL数据库一共设置了四个事务隔离级别,分别是,READ-UNCOMMITTED(读未提交),READ-COMMITTED(读提交),REPEATABLE-READ(可重复读),SERIALIZABLE(串行)
允许当前未提交的事务读取其它事务未提交的内容,隔离级别最低,脏读,不可重复读,幻读都不能避免。
允许当前未提交的事务读取其它事务已提交的内容,隔离级别比读未提交好,可以避免脏读,但是不可重复读,幻读都不能避免。
读提交演示,先将数据隔离级别设置为读提交,虽避免了脏读,但出现了不可重复读
事务交叉执行时不允许当前未提交的事务读取其它事务在此时已提交的内容,隔离级别比读提交好,可以避免脏读,不可重复读,但是幻读不能避免。
可重复读演示,先将数据隔离级别设置为可重复读,避免了脏读和不可重复读,出现了幻读
事务不能并发执行,所有的事务都必须一个接一个执行,即串行。
串行演示如下,先将数据隔离级别设置为串行,避免了脏读,不可重复读,幻读。
本文主要讲解了什么是事务,事务的特性,以及数据库并发所带来的问题,最后点题事务的隔离级别是的这些问题在可控范围之内。
事务隔离级别 \并发问题 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 不能避免 | 不能避免 | 不能避免 |
读提交 | 能避免 | 不能避免 | 不能避免 |
可重读 | 能避免 | 能避免 | 不能避免 |
串行 | 能避免 | 能避免 | 能避免 |
总之来说,事务的隔离级别越高,数据就越安全,但是并发性能就越差。建议平常在使用过程中,在数据安全性可控的前提下,尽可能的降低事务的隔离级别以提高性能。