就是说你定义一组数据库操作,然后告诉数据库说这些操作要么都成功,要么都不成功。
类似于网购买东西:你付完款,商家必须把东西寄到你的手上,期间无论是库存、快递、快递员、商品质量等任何一个环节出问题,商家必须把钱退回给你。那么买东西,就是一个事务。
事务的特性有四种--ACID:
- 原子性(Atomic):这个强调事务的根本特性,一个事务内的所有操作必须像原子操作一样,要么都成功要么都失败,不能再拆分了。
- 一致性(Consistent):这个强调数据的完整性。就是说事务修改前后,数据符合逻辑上的完整性。就像包裹从仓库寄到你家,手机不能变成砖头。
- 隔离性(Insulation):这个强调的是两个并发的事务应该是互不干扰的。虽然两个包裹都是从北京寄到上海,但是A包裹被退回时,买家和卖家都没必要去管B包裹是啥情况。
- 持久性(Duration):这个强调事务完成后对数据库的影响是永久的,进入一个稳定的状态。这个是相对于事务的实现来说的,数据库为了维持一个事务,需要做很多缓存或者临时性的操作。持久性就是在事务结束后,这些临时操作都正式生效了。比如你手机确认收货后,买手机的过程就正式完成了。对于卖家来说,再有别的问题,那就是售后的问题,而不是销售的问题了。
相信读者在看到事务的隔离性时,就会有疑问:两个并发的事务不能同时修改同一条数据,那同时读一条数据时怎么办呢?
这就会涉及数据库对事务的隔离控制:很明显,不能让两个并发的事务同时修改同一条数据,但是照顾到性能,也不能不让两个事务同时读同一条数据吧?“查询”这么无公害的操作,何必要赶尽杀绝呢?
先看看,如果两个事务同时操作同一条数据,会带来哪些问题:
1.丢失更新:当前余额为:1,A事务的功能是把余额+1;B事务的功能是把余额-1;它俩同时读到了余额为0,悲剧就发生了。。。。
2.脏读:A事务正在把userName改成‘bizi’,还没有提交,B事务来读取userName,得到了‘bizi’,但是A事务在修改age时抛了异常,因此回滚,结果B事务就悲剧了。。。。
3.幻读:A事务读了一下当前的订单数目,B事务过来新增加了一个订单,A事务又读了一次订单数,读了两次竟然结果不一样,闹鬼了。。。
4.不可重复读:A事务读取了某条数据,B事务过来修改了这条数据并提交,A事务再读的时候,就发现跟刚刚不一样哎。。。
不可重复读跟脏读的区别:
脏读读取的是未提交的数据,很有可能是无效的数据。而不可重复读读取的是提交之后的数据,最起码第二次读对了
不可重复读跟幻读的区别:
幻读读的是一整条记录,而不可重复读针对的是某一个或几个特定字段。
那么为了避免这种情况,数据库就设定了几种隔离级别,供我们使用:
1.串行化(Serializable):不允许事务并发,大家排好队,上一个事务提交(或回滚)了,下一个事务再执行。
2.可重复读(Repeatable-Read):同一事务前后两次的读,保证数据一致。意思就是:读的时候,不允许别人写。但是允许别人插入别的数据,因此不能避免幻读。
3.读已提交(Read Commited):只允许事务读取被其他事务提交的数据。意思就是:如果当前事务是修改数据,那么不允许读。因此避免脏读,但是不能避免幻读和不可重复读。
4.读未提交(Read Uncommitted):允许事务读取其他事务还未提交的数据。因此上述问题都会发生。
一个表格可以说明一切(来源于@jiajialin:http://blog.csdn.net/jialinqiang/article/details/8723044):
来自为知笔记(Wiz)