JPA进阶–事务隔离
JPQL查询
JPQL和SQL很像,查询关键字都是一样的
唯一的区别是:JPQL是面向对象的
规则
JPA的查询语言,类似于sql
里面不能出现表名,列名,只能出现java的类名,属性名,区分大小写
出现的sql关键字是一样的意思,不区分大小写
不能写select * 要写select 别名
事务
事务四个特性:
原子性
一组操作不可分割(同生共死)
一致性
操作结果动态一致(能量守恒)
隔离性
同时多个线程操作,相互没有影响
持久性
修改以后将数据保存到数据库中
事务产生的问题
1.丢失更新
当事务A和事务B同时修改某行的值,
事务A将数值改为0并提交,购买了一件
事务B将数值改为0并提交,也购买了一件。这时数据的值为0,事务A所做的更新将会丢失。(相当于就卖出去2件商品)
2.脏读
读取未提交数据,A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据
3.幻读
前后多次读取的数据总量不一致
事务A在执行读取操作,需要两次统计数据的总量,前一次查询数据总量后,此时事务B执行了新增数据的操作并提交后,这个时候事务A读取的数据总量和之前统计的不一样,这便产生了幻读
4.不可重读读
前后多次读取,数据内容不一致
事务A将自己读取了自己的年龄为18,此时操作还在继续,这时候事务B修改了事务A的年龄为20,提交了事务,事务A再次读取自己的年龄时变为了20
(面试必问)数据库事务的隔离机制(4种)
READ UNCOMMITTED(未提交读)
这个级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,被称为脏读(Dirty Read),这个级别性能不会比其他级别好太多,但缺乏其他级别的很多好处,一般很少使用。
READ COMMITTED(提交读)
这个级别是大多数数据库系统的默认隔离级别(但MySQL不是)。一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别也叫作不可重复读(nonrepeatable read),因为两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读)
该级别保证了在同一个事务中多次读取同样记录的结果是一致的,但依然无法解决另外一个幻读(Phantom Read)的问题。幻读,指的是当某个事物在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB 和 XtraDB 存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。可重复读是MySQL的默认事务隔离级别。
ERIALIZABLE(可串行化)
最高的隔离级别,强制事务串行执行,避免了前面说的幻读的问题。但每次读都需要获得表级共享锁,读写相互都会阻塞
对于隔离机制,我们一般使用默认的即可
悲观所
给事务加上锁,同一时间只允许一个线程进操作,如果事务没有被释放,就会造成其他事务处于等待,效率低,一般不太用到
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,允许同时读取,但是不可以修改
使用乐观锁实现一个秒杀场景
实体类
1 | package com.ifueen.domian; |
测试
1 | package com.ifueen.test; |