数据库事务再次理解
事务只提要求,下面都是实现
隔离级别:
0读未提交:读到未提交数据(比如发生事务回滚时,事务的一致性要求不能读取未提交的数据)
1读已提交:读到的都是已提交数据
2可重复读:事务中多次读取数据一样(因修改记录的情况)
3幻读:事务中多次读取数据不一样(因新增/删除记录的引起)
工作中,有设计到数据库事务的,看来还得学习下。
Oracle默认隔离级别: 1级(0,1、2、3),读已提交。
Mysql默认级别:2级, 可重复读
为什么它俩选择了不同的默认的级别?可能没有标准答案,但是可以去探究主要原因。
这个隔离级别,是否意为着需要我们自己解决剩下的问题,不如Oracle,程序员自己要解决可重复读和幻读的问题。
我们使用到事务的常规代码1:
@Transaction
function(param){
select
....
update/delete
}
我们要明白这个执行过程,首先在进入方法时,会创建一个事务。这是如果在3隔离级别下,
有事务没有提交,则需等待。
如果时oracle使用1,则怎么半呢?不会等待,直接读取提交的数据,此时如果没有额外的处理,会导致多个事务先后提交时,这个时候就会出现不一致性(和代码变量中的并发一样)。
此时如果设置了行锁,则在事务开始时进行了锁获取,否则等待。不然在提交时以谁的为准呢?只是一般事务完成很快,感受不到罢了。在行锁控制中,获取到锁的事务没有提交,其他update事务就无法开始和提交,就实现了可重复读(事务中多次读取一样)。但是幻读(新增数据)会存在吗?会,因为它不能阻止新增的事务的新增数据。典型的比如,对符合条件的2条数据修改,但是新增的也符合一起修改了,如果在事务再次读取,则会不一样(不符合事务的定义)
但是幻读还是没法彻底避免,包括MVCC机制,只是尽可能减少。解决幻读,必须要用串行化思想。
- 案例讲解
代码2
@Transaction
function(param){
select
....
update
}
比如我们的代码存在代码1,不存在设计新增数据的读写,那就不存在幻读问题。只需解决可重复读问题。
可以以一条记录为基本,对其不断增长,然后作为插入唯一约束的表中,在并发情况下,就会看到数据的报错。