java SSM第三章学习内容(事务,SQL语句锁表,DB死锁,隔离级别,Spring上锁)

一.事务
 

数据库必须具备的四个特性

1:原子性:事务包含的所有操作要么全部成功,要么全部失败回滚;成功必须要完全应用到数据库,失败则不能对数据库产生影响;

2:一致性:事务执行前和执行后必须处于一致性状态,

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

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

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



事务只要分为
1.编程式事务

    1.1完整事务(以前编辑的SQL语句,完全提交或完全回滚,完整事务分为显式跟隐式)
        1.1.1显式事务:
              手动打开,编辑sql,手动提交
              begin transaction
                    update
        1.1.2隐式事务
              自动打开,编辑sql,自动提交
              
    1.2部分事务(一部分提交,一部分回滚,前面提交后面回滚)
         1.2.1 savepoint sp1  定一个点,用于回滚
                  roll back to sp1  回滚到指定的点

    1.3只读事务
          设置只能查询,跟锁表不一样,锁表对操作的某一列锁死,而事务是把整表锁死
         1.3.1   set transaction read only  设置只读
         1.3.2   commit            解锁

    1.4独立事务(又叫默认事务自动提交事务,oracel没有)
         1.4.1   执行一条语句就是一次事务,自动提交,无法回滚

    1.5孤独事务(oracel没有)
         1.5.1   当系统原因导致语句异常
2.声明式事务(7种)
 

扫描二维码关注公众号,回复: 3222732 查看本文章


二.SQL语句锁表

不缩表可能引发:

1丢失修改
2.不可重复读
3.读"脏"数据


锁表:防止同时执行或操作

 

select * from 表名 lock in share mode;        普通锁(读锁,乐观锁S),别人不能同时查询访问

select * from 表名 for update;            高级锁(写锁,悲观锁X),修改删除之前必须上锁

commit;                    解锁

select * from 表名 where 属性="xx"  for update;    根据条件锁执行的数据

select * from 表名 where 属性="xx"  for update wait 20;    wait 以分钟锁表

注:查询条件大的应该放前面,例如条件查询'男'and name='张三',查询数据多的应该放在前面



 

三.DB死锁


A读取或则修改一个数据会进行上锁,A锁死后B其他互不相让,mysql会自动检查死锁随机开启一个




 

四.隔离级别  4个级别
 

01:脏读

是指一个事务处理过程里读取了另一个未提交的事务中的数据,然后使用了这个数据;
例:用户A向用户B转账100元,A通知B查看账户,B发现前确实已到账,而之后无论第二条SQL是否执行,只要该事务部提交,则所有操作都将回滚,当B再次查看账户时就会发现前其实并没有到账。

02:不可重复读
不可重复读是指在一个事务内,多次读取同一个数据,在这个事务还没有结束 ,另一个事务也访问该同一数据,但是由于第二个事务的修改,那么第一个事务两次读取的数据可能不一样,因此称为不可重复读;即同一个事务中原始数据读取不可重复。 注:不可重复读和脏读的区别,脏读是某一个事务读取另一个事务未提交的脏数据; 不可重复读则是读取前一事务提

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

 

01:Read uncommitted(读未提交):最低级别,任何情况都会发生。
02:Read Committed(读已提交):可避免脏读的发生。
03:Repeatable read(可重复读):可避免脏读、不可重复读的发生。
04:Serializable(串行化):避免脏读、不可重复读,幻读的发生。

SQL中设置的语句:set session transaction isolation level read uncommitted;     完全可读

 

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

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

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

下面就四种隔离级别进行场景设计:

01: Read uncommitted 读未提交; 公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有2000元,singo空欢喜一场。

02:Read committed 读已提交; singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为何......

03:Repeatable read 重复读 当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

04:重复读可能出现幻读: singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

五.Spring上锁

1.XML上锁

2.注解上锁

已写在---java SSM第三章学习内容(Spring与Mybatis整合的方式四:注解,五:事务,六:事务注解)

猜你喜欢

转载自blog.csdn.net/JayVergil/article/details/81261135