事务及其并发问题
大家好,我是一只学弱狗,记录学习的点点滴滴!
优质文章
- 一张黄图的故事
- JavaSE练习项目-坦克大战
- 我是菜鸟、我小试牛刀
- linux指令太多记不住?小白看这篇就够了!
优质专栏
- 数据库就该这样学
- 爪哇外步篇
事务:事务是由一个或一组SQL语句组成的一个执行单元,这个执行单元要么全部执行,要么全部不执行
事务的ACID属性
- 原子性(Atomicity):是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
- 一致性(Consistency):是指事务必须使数据库从一个一致性状态变换到另一个一致性状态
- 隔离性(Isolation):是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
- 持久性(Durability):是指一个事务一旦被提交,它对数据库中的数据的改变就是永久性的,接下来的其它操作和数据库故障不应该对其有任何影响
事务的创建
事务分为隐式事务和显式事务
- 隐式事务:事务没有明显的开启和结束的标记,比如insert、update、delete语句
- 显式事务:事务具有明显的开启和结束的标记
我们具体来说一下显式事务的创建,它一个前提:必须先设置自动提交功能为禁用,我们执行下面这条语句
SHOW VARIABLES LIKE 'autocommit';
出现下面的结果
可以看到自动提交(autocommit)的值为ON,为自动开启状态,这也是我们平时所写的的insert、update、delete语句可以代表一个事务,接下来我们先用下面的代码来创建一个表并插入数据
USE test;
DROP TABLE IF EXISTS account;
CREATE TABLE IF NOT EXISTS account(id INT,username VARCHAR(20),salary DOUBLE
);
INSERT INTO account VALUES(1,'Alice',1000);
INSERT INTO account VALUES(2,'Boily',1000);
我们开始创建事务,通过下面的一条语句设置自动提交为禁用
SET autocommit=0;
再看一下autocommit的值
已经关闭了自动提交,我们继续执行
SET autocommit=0;
UPDATE account SET salary=500 WHERE id=1;
UPDATE account SET salary=1500 WHERE id=2;
COMMIT;
上述代码即一个事务执行之后,我们查看表的内容
达到了预期的结果,我们再来执行下面的语句
SET autocommit=0;
UPDATE account SET salary=1000 WHERE id=1;
UPDATE account SET salary=1000 WHERE id=2;
ROLLBACK;
没有报错,我们再来看下结果
问题出现在COMMIT和ROLLBACK,COMMIT是提交事务,ROLLBACK意为回滚点,大家可以想一下这么一个场景:你双十一购物的时候,看上了一个东西,订单都提交了,当你付钱的时候,发现没钱了,于是呢,这个订单就会失败,而不会提交,大概就是这么一个意思。。。
事务的并发问题
事务的并发问题有下面这几类
- 脏读:是指对于两个事务T1、T2,T1读取了已经被T2更新但还没有被提交的字段,之后,若T2回滚,T1读取的内容就是临时且无效的
- 不可重复读:对于两个事务T1、T2,T1读取了一个字段,然后T2更新了该字段,之后,T1再次读取同一个字段,值就不同了
- 幻读:对于两个事务T1、T2,T1从一个表中读取了一个字段,然后T2在该表插入了一些新的行,之后,如果T1再次读取同一个表,就会多出几行字段
接下来,我们将通过命令行的方式来解读一下上面的三个并发问题,当然,在这之前,我们需要了解一些知识:
在MySQL中,为了避免上面的并发问题,采用了隔离机制,即设置事务的隔离级别,在MySQL中,一共有四种隔离级别,如下
事务的隔离级别
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
我们可以通过下面两条语句来查看隔离级别和设置隔离级别
select @@tx_isolation;#查看隔离级别
set session transaction isolation level 隔离级别;#设置隔离级别
好,我们开始通过命令行的方式,设置不同的隔离级别来了解三种并发问题
隔离级别:READ UNCOMMITTED
打开命令行窗口,查看MySQL默认的隔离级别,如下
可见,MySQL默认的隔离级别是REPEATABLE READ,现在,我们把它设置为READ UNCOMMITTED,如下
设置成功之后,我们查看下表account中的内容,如下
我们开始创建事务,同时,我们再打开一个命令行窗口,如图
这样,就演示了脏读的效果,接下来,我们来演示不可重复读
继续演示幻读
好,对于当隔离级别为READ UNCOMMITTED时的三种并发问题我们就演示到这里。
隔离级别:READ COMMITTED
和前面一样,恢复数据后,我们继续演示
可见,在这种隔离级别下,可以避免脏读问题,接下来,我们看下不可重复读和幻读
可见,在这种隔离,仍避免不了不可重复读和幻读
隔离级别:REPEATABLE READ
我们恢复数据,继续演示
避免了脏读问题,我们看一下不可重复读
这种隔离级别避免了不可重复读,再来看看它对幻读能否避免???
还是没能避免幻读!!!
隔离级别:SERIALIZABLE
终于,到了最后一个了
我们直接试下看它能否避免幻读
终于避免了,其实在这种隔离级别下,三种并行都能够避免
隔离级别总结
- READ UNCOMMITTED:出现脏读,不可重复读,幻读
- READ COMMITTED:避免脏读,出现不可重复读和幻读
- REPEATABLE READ:避免脏读和不可重复读,避免幻读
- SERIALIZABLE:避免脏读,不可重复读,幻读
发布评论