1. 事务特性和事务的隔离级别

        数据库部分,我开篇就进入事务部分的讨论。因为我觉得这块是数据库比较核心重要的内容。

        大学学过数据库原理的,基本上都能脱口说出数据库的四大特性:ACID。可是真正深入理解了吗?我们再来重新看一下这四大特性:

  •  原子性( Atomicity ):一个事务中是包含多个CRUD操作的,因此事务的第一个要求就是,这些操作应该全部成功或全部失败,怎么保证呢?很简单,执行过程中有异常,回滚操作即可。生活中常见的转账场景,A给B转300块钱,假设在同一个数据库操作,第一条sql:A的账户减去300,第二条sql:B的账户增加300,两个sql同时成功转账成功,同时失败转账失败;
  • 一致性( Consistency ):对于一致性,我是这么理解的:就是事务前和事务后,数据库是从一个正确状态变更到了另一个正确状态,否则事务回滚。怎么解释这句话呢?我们还用上面转账的例子,如果A的账户里只有280块钱了,没有任何限制的情况下数据库是能执行成功的,执行后的结果是A账户余额-20,可是我们都知道这在业务上是不允许的,也就是说如果这样操作数据库就从之前的正确状态变更到了一个错误的状态上来。为保证一致性, A的账户余额>=300的时候,我们才能允许成功。保障一致性我目前想到两个方法,一是数据库保证,事务执行后,通过数据库机制来检测是否状态都正确(触发器),二是通过应用程序保证,这个就简单了,应用层增加业务校验即可。
  • 隔离性( Isolation ):隔离性是说多个事务执行的时候是互不干扰的,自己执行自己的,谁也无法看到其他事务的数据。但是这里就会引发好多问题了,如果Java里多线程带来的复杂性一样,这里后面会展开讨论。
  • 持久性( Durability ):一个事务完成后,执行结果是要持久化保存的。其实这里就是要求必须进行数据库的commit操作,数据库的commit就是从回退段中永久性的写入数据表空间的操作。

        同时满足以上四个特性时,才是一个完整的事务。再进一步思考一种这样的情况 ,大量的并发情况下,有两个这样的事务,事务T1中是这样的语句:

        1. select state from A where id=1; 

        2. update B set  status = '0' where id=1;

        事务T2中是这样的语句:
        3. update A set state='1' where id=1; 

        4. select status from B where id=1;

        已知当前 A表中id=1的 state='0',B表中id=1的status='1',如果两个事务是并发执行的,那么语句1的select查到的结果是什么?语句4select查到的结果是什么?答案是不知道,因为我们不知道语句1先执行还是语句3先执行,2和4同理。那么有没有办法控制呢?有,那就是引入事务的隔离级别。这也是我们大学学过的内容。先说说四个隔离级别吧:

  • 读未提交(read uncommited):事务可以读到其他事务已修改未提交的数据。这种隔离级别下,如果语句在时间顺序上执行的是 1、3,那么1的结果就是state='0',如果顺序是3、1,那么1的结果就是state='1';如果读到了事务T2未提交的数据,而T2又因为执行错误回滚,事务T1读到的数据就是脏数据,这种情况称为脏读。
  • 读已提交(read commited):事务读到的都是其他事务已提交过的数据。这种隔离级别下,如果语句1执行时,T2未提交,则语句1读到state='0',如果T2提交则读到state='1',不会读到未提交的数据了。但是,新的问题来了,如果T1中有又增加了语句5,语句5跟语句1一样,那么1和5的结果可能不一样吗?答案是有这种概率。如果 执行时间顺序是这样的,1 ,事务T2提交,5,这样1和5读到的数据就不一致了,同一个事务中同一条语句读到了不同的数据?这种情况就称之为不可重复读。有办法解决吗?有!就是语句1读取的时候,把读到的数据加锁,不允许再修改,直至事务提交或回滚再释放锁。
  • 可重复读(read repeatable):事务内部对数据的读取前后是一致的。这种隔离级别解决了不可重复读的情况,实现方案前面也提到了,就是加锁。但是还有一种情况,你是锁不住的,那就是T2中有insert怎么办?语句1的where 条件去掉,这样语句1 就是查询所有数据了,这时候把读出来的数据都锁住,别的事务不允许操作,但这时候T2给A表新增了一条数据,并在事务T1提交前提交的。事务T1以为处理了所有的A表数据,但发现多出来一条其他数据。这种情况称为幻读
  • 串行读( Serializable):完全串行化读,使用表级锁,读和写都会阻塞。这种情况下,数据库的并非能力受限、性能不高,但数据的正确性有保障。

        总结下事务的隔离,我们整理出下表:

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
未提交读(Read uncommitted)可能可能可能
已提交读(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(Serializable )不可能不可能不可能

 

 

转载于:https://my.oschina.net/u/3293327/blog/3037179

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值