事务管理

2 篇文章 0 订阅
1 篇文章 0 订阅

一、事务的概述

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

二、MYSQL命令行窗口事务的常用操作

1.开启事务:           start transaction

2.提交事务:           commit

3.回滚事务:         rollback

三、事务的特性

1.原子性

组成事务的各个逻辑单元不可分割,事务包含的所有操作要么全部成功,要么全部失败回滚;成功必须要完全应用到数据库,失败则不能对数据库产生影响;

2.隔离性

当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不被其他事务的操作所干扰,多个并发事务之间要相互隔离;

3.持久性

一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便在数据库系统遇到故障的情况下也不会丢失事物的操作。

4.一致性

事务执行前和执行后必须处于一致性状态,  例:用户A和用户B的前加起来一共是5000; 无论AB用户之间是如何相互转换的,事务结束后两个用户的钱加起来还是5000,这就是事务的一致性。

四、隔离级别

隔离性:当多个线程都开启事务来操作数据库中的数据时,数据库系统要进行隔离操作,以保证各个线程获取数据的准确性。 不考虑事务的隔离性,会产生的几种问题:

1:脏读

一个事务读到了另一个事务未提交的数据 ,导致多次查询结果不一致 
例:用户A向用户B转账100元,A通知B查看账户,B发现前确实已到账,而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,当B再次查看账户时就会发现前其实并没有到账。

2:不可重复读

一个事务读到了另一个事务已经提交update的数据,导致多次查询结果不一致。
不可重复读是指在一个事务内,多次读取同一个数据,在这个事务还没有结束 ,另一个事务也访问该同一数据,但是由于第二个事务的修改,那么第一个事务两次读取的数据可能不一样,因此称为不可重复读;即同一个事务中原始数据读取不可重复。

注:不可重复读和脏读的区别,脏读是某一个事务读取另一个事务未提交的脏数据; 不可重复读则是读取前一事务提交的数据

3:幻读:

一个事务读到了另一个事务已经提交insert的数据,导致多次查询结果不一致。

当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行修改,这种数据涉及到表中的全部数据行,同时,第二个事务也对这个表数据进行修改,这个修改是对表中新增/删除一条数据,那么操作第一个事务的用户发现表中的数据还没有修改的数据行,就好像发生了幻觉一样,这就是发生了幻读。
注:幻读和不可重复读都读取另一条已经提交的事务,所不同的是不可重复读查询的都是同一数据项,而幻读针对的是一批数据整体。

 
数据库提供的四种隔离级别:
01:Read uncommitted(读未提交):最低级别,任何情况都会发生。
02:Read Committed(读已提交):可避免脏读的发生。(oracle默认级别)
03:Repeatable read(可重复读):可避免脏读、不可重复读的发生。(mysql默认级别)
04:Serializable(串行化):避免脏读、不可重复读,幻读的发生。
 

注: 四种隔离级别最高:Seralizable级别,最低的是Read uncommitted级别; 级别越高,执行效率就越低; 隔离级别的设置只对当前链接有效,对JDBC操作数据库来说,一个Connection对象相当于一个链接,只对该Connection对象设置的隔离级别只对该connection对象有效,与其它链接connection对象无关。

01:Mysql的默认隔离级别是:可重复读:Repeatable read;

02:oracle数据库中,只支持seralizable(串行化)级别和Read committed();默认的是Read committed级别;

五、安全问题演示

【事物】演示脏读

  1. 开启两个窗口A,B
  2. 设置A窗口的隔离级别为read uncommitted;

SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;

  1. 在A,B两个窗口中开启事务

start transaction;

  1. 在B窗口中完成转账的功能:

update account set money = money - 1000 where name= '小张';

update account set money = money + 1000 where name= '小凤';

-- 这里不提交事物

  1. 在A窗口中进行查询

select * from account;

发现A窗口中已经查询到转账成功了!!!已经发生了脏读:一个事务中已经读到了另一个事务未提交的数据。

【事物】避免脏读

  1. 开启两个窗口A,B
  2. 设置A窗口的隔离级别为read committed;

SET SESSION TRANSACTION ISOLATION LEVEL read committed;

  1. 分别在两个窗口中开启事务:

start transaction;

  1. 在B窗口中完成转账

update account set money = money - 1000 where name= '小张';

update account set money = money + 1000 where name= '小凤';

-- 没有提交事物

  1. 在A窗口中进行查询:

select * from account;

发现这个时候没有转账成功!!!(没有查询到另一个事务未提交的数据:说明已经避免了脏读)。

  1. 在B窗口中提交事务

commit;

  1. 在A窗口查询

select * from account;

发现这次的结果已经发生了变化!!!(已经发生不可重复读:一个事务已经读到了另一个事务提交的update的数据,导致多次查询结果不一

【事物】避免不可重复读

  1. 分别开启两个窗口A,B
  2. 设置A窗口的隔离级别:repeatable read;

SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;

  1. 在A,B两个窗口中开启事务:

start transaction;

  1. 在B窗口完成转账

update account set money = money - 1000 where name= '小张';

update account set money = money + 1000 where name= '小凤';

-- 没有提交事物

  1. 在A窗口中进行查询

select * from account;

发现没有转账成功:说明避免脏读!!!

  1. 在B窗口中提交事务

commit;

  1. 在A窗口中再次查询:

select * from account;

发现在一个事务中的多次查询结果是一致!!!(已经避免不可重复读)

【事物】避免虚读/幻读

  1. 开启两个窗口A,B
  2. 设置A窗口的隔离级别:serializable
  3. SET SESSION TRANSACTION ISOLATION LEVEL serializable;

  1. 分别在两个窗口中开启事务:
  2. start transaction;
  3. 在B窗口中插入一条记录
  4. insert into account values (null,'小李',10000);
  5. 在A窗口中进行查询
  6. select * from account;

发现A窗口已经卡住了(说明事务不允许出现并发,A窗口需要等待B窗口事务执行完成以后,才会执行A窗口的事务。)当B窗口的事务结束(提交或者回滚),那么A窗口马上就会出现结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值