数据库事务学习练习总结

四个特性

原子性:操作一组指令,要么全部成功,要么全部失败。

一致性:比如转账,无论你做什么操作,最后的总钱数不会改变。

隔离性:两个事务并发进行,并发事务之间要相互隔离。

持久性:事务完成后,对数据的改变是永久的。

并发事务导致的问题

脏读:一个事务读取了另一个事务未提交的数据,之后未提交的事务回滚了。

幻读:一个事务执行两次,发现查询到的数据多了,或者少了。

不可重复度:事务A读取了一个数据 num = 1,事务A还没有提交,但是事务B修改 num = 2 提交了, 事务A再次读物num的时候,发现数据变了。

脏读和不可重复读的区别:脏读是A事务读取了B事务没有提交的数据,然后B事务回滚了

​ 不可重复读是A事务读取了B事务没有提交和提交后的数据。

事务的隔离级别

读未提交:顾名思义,就是一个事务可以读取到另一个事务没有提交的事务,可能出现脏读。

​ 解决:Read committed (读提交)

读提交:就是一个事务需要等到另一个事务提交之后才能读取数据,可能会出现不可重复读。

​ 解决:Repeatable read(重复读)

重复度:开始读取数据的时候(事务开启),不再允许修改操作。但是可能会出现幻读。(mysql不存在幻读,因为mysql的innodb引擎实现RR的时候加了间隙锁)

​ 解决:serializable (序列化)

序列化:最高级别的事务隔离级别,事务串行化顺序执行。(一般不使用)

事务的七大传播行为

PROPAGATION_REQUIRED: A事务方法调用B事务方法,如果A事务方法的事务存在,那么B事务就 在A事务中运行,如果A事务不存在,那么就新建一个事务运行。

​ 回滚:

​ A事务如果存在,B事务就和A事务共用一个事务,那么无论哪儿发生异常,AB都会回滚

​ A方法事务如果不存在,B事务会新建一个事务,那么只有B方法发生异常,才会导致B事 务回滚,A方法不受影响。

PROPAGATION_REQUIRES_NEW:A事务方法调用B事务方法,不管A事务是否存在,都会新建一个 事务来运行B事务。

​ 回滚:如果B事务发生异常,A事务也会跟着回滚

​ 如果A事务发生异常,B事务不会跟着回滚

上面两个是最常用的两种事务。

PROPAGATION_SUPPORTS: 支持当前事务,假设当前没有事务,就以非事务方式运行

PROPAGATION_MANDATORY:支持当前事务,假设当前没有事务,就抛出异常

PROPAGATION_NOT_SUPPORTED:以非事务方式运行操作。假设当前存在事务,就把当前事务挂起

PROPAGATION_NEVER:以非事务方式运行,假设当前存在事务,则抛出异常

PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED类似的操作。

事务方法的嵌套调用问题:

在一个service内部,事务方法之间的嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务,因为spring的事务是通过动态代理实现的,但是动态代理最后都是要用原始对象调用方法的,原始对象调用就不会再次触发代理了。

解决方法:用代理对象去调用,spring的ioc用的就是动态代理,用@AutoWride注入的对象去调用这个方法就可以了。

MYSQL行锁表锁

用一个没有索引的字段做条件-----------表锁

这个事务还没提交,我又发起一个事务

这个事务就会等待上一个事务释放锁,但是我这儿更新的不是同一行。所以应该是表锁。

用主键做条件

再发起一个更新请求:

提交成功了!!

再试试修改同一行的数据:

再发起一个修改请求:

嘿嘿嘿:果然在等待锁。

如果用其他的索引做条件呢??

修改同一行数据会出现等待锁的现象。

但修改不同行的数据不会

所以innodb的表锁行锁问题:如果普通的crud是表锁,但是如果索引生效的crud就是行锁

posted @ 2019-12-03 16:40  嘿,笑一个  阅读(442)  评论(0编辑  收藏  举报