java学习之mysql之事务

一、事务

数据库事务的百度百科解释:数据库事务( transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
我的理解是:事务是对一个数据库操作的完整操作,比如银行转账,这个事务的完成是用户A的钱已经减少,用户b的钱增加完成,此时可以是一个事务。

数据库事务的四大特性:

百度百科解释:
1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么全部不执行。
2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序 串行执行的结果相一致。
3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的。
4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。
我的理解:
1、原子性(Atomicity):不能再分割,要不一起成功,要不一起失败回滚(如转账)
2、一致性(Consistency):指数据从一个一致性状态转为另一个一致性状态。(比如转账,A和B的账户上一共只有2000元,无论A和B之间怎么转账操作,A和B的总钱数不变都是2000元)
3、隔离性(Isolation):事务的执行不受其他事务的干扰,每一个事务都属独立的。
4、持久性(Durability):数据库会把提交的数据持久化到本地存储,意味着数据时永久改变的。

以事务的方式对数据库进行访问,有如下的优点:

1、把逻辑相关的操作分成了一个组;
2、在数据永久改变前,可以预览数据变化;
3、能够保证数据的读一致性。

事务的隔离级别

首先了解一下在没有事务隔离的时候,可能会会有的情况。
1、两个更新事务同时修改一条数据。(情况最严重,会造成更新的丢失)

2、一个事务更新一条数据时,另一个事务读取了还没提交的更新。(脏读)
例子:A转账500元给B,此时分为两步,A先减少500元,B再增加500元,如果没有事务隔离,当A减少500元,但是还没有提交时,另一个C可能在查看A和B的钱,发现已经A已经少了500元,B还没有增加500元,此时就是脏读。

3、一个读取事务读取一条数据时,另一个更新事务修改了这条数据,这时就会出现不可重现的读取。
例子:C先查询A的钱数,A再转账,把500元转走了,此时C再查询钱数,发现A的钱少了500。
4、一个读取事务读取时,另一个插入事务(注意此处时插入)插入了一条新数据,这样就可能多读出一条数据,出现幻读。
总结:
前三种都是对同一条数据的并发操作,对程序的结果可能产生致命影响,尤其是金融等实时性,准确性要求极高的系统,相比第四种情况不会影响数据的真实性,在很多情况下是允许的,如社交论坛等实时性要求不高的系统!

隔离等级内容结果
READ UNCOMMITTED读未提交会出现脏读、不可重复读、幻读
READ COMMITTED读已提交会出现不可重复读、幻读
REPEATABLE READ可重复读会出现幻读(mysql不会)
SERIALIZABLE串行化相当于给表加了锁,如果B想操作表,必须等A结束

具体演示

相关代码

-- 查看当前会话的默认隔离级别
SELECT @@tx_isolation;

-- 设置mysql的隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 开启事务
start TRANSACTION;

-- 提交
COMMIT;

脏读

是mysql的隔离级别为READ UNCOMMITTED(读为提交)时,会出现的问题。
一、先把两个线程的事务隔离级别设置好
线程一是navicat程序:
设置级别为READ UNCOMMITTED:

-- 先设置mysql的隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

-- 再查看当前会话的默认隔离级别
SELECT @@tx_isolation;

运行结果:
在这里插入图片描述
线程二是cmd打开的mysql运行窗口:
在这里插入图片描述

2、初始 user 表的内容:
在这里插入图片描述
3、运行代码为:

-- 开启事务
start TRANSACTION;
insert into user VALUES(2,'王佳琪','男',1111);

4、执行代码后user表的内容还是
在这里插入图片描述
5、但是cmd里面的user查询内容为:
在这里插入图片描述
此时就出现了数据还未提交保存到user中,但是另一个线程已经可以读取了。

不可重复读

是隔离级别为READ COMMITTED或READ UNCOMMITTED时会出现的问题,此时我设置READ COMMITTED(读已提交)的隔离级别
1、还是先设置两个线程的隔离级别
还是执行代码:

-- 查看当前会话的默认隔离级别
SELECT @@tx_isolation;

-- 设置mysql的隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

在这里插入图片描述
2、因为我不知道sql的线程睡眠函数,所以我是使用把一个非常大的表user2执行查询来当成睡眠使用。初始 user表的内容
在这里插入图片描述3、执行代码
第一线程执行

vSELECT * from user;
SELECT * from user2;
SELECT * from user;

第二个线程执行:
在这里插入图片描述
4、执行结果为:
第一次查询:
在这里插入图片描述
第二次查询为:
在这里插入图片描述
此时就出现了在同一个线程执行的两次查询,结果不一致的情况,此时就是不可重复读的情况了

REPEATABLE READ(可重复读)

由于mysql中的 REPEATABLE READ(可重复读)级别已经默认解决了幻读的问题,所以幻读没法演示了。而且在mysql中已经不需要用SERIALIZABLE。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值