事务的四个特性 (ACID) ,分别是原子性( Atomicity), 一致性( Consistency), 隔离性( Isolation), 持久性( Durability)。一致性是事务的目的,原子性,隔离性,持久性是一致性的必要条件。
隔离性:多个并发事务之间要相互隔离,对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
隔离级别有四种:
1、Serializable :最严格的级别,事务串行执行,资源消耗最大。
2、REPEATABLE READ :保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
3、READ COMMITTED :大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。
4、Read Uncommitted :读取过程中会读取到非法数据。
不可重复读、脏读、幻读的区别:
脏读是某一事务读取了另一个事务未提交的脏数据。
不可重复读则是读取了前一事务提交的数据,在某些情况下,不可重复读并不是问题,以最终查询的结果为准。
不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
四种隔离级别与读取事务和写事务:
读取未提交,读不会阻塞任何事务,写只阻塞写,会导致读出现脏读、不可重复读、幻影读。
读取已提交,读不会阻塞任何事务,写阻塞读、写,因为写阻塞读,排除“脏读” 问题,但是读还是不阻塞写,不可重复读、幻影读会出现。
可重复读,读只阻塞写,写阻塞读、写,读阻塞写避免了“不可重复读”的问题,但是读事务并没有阻塞对数据库的插入操作,所以此 时“幻影读”问题照样存在。
Serializable 数据库系统会保证执行此种隔离级别事务的效果和顺序执行的效果一致。
默认的隔离级别:
在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。
而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。
并发控制:
在每个读的数据行上加上共享锁
此时我们一般采用READ COMMITTED的隔离级别,然后再结合以下几种并发控制的锁定策略:
* 乐观所
* 悲观锁
* 乐观离线锁
* 悲观离线锁
此时其实并发是由应用程序来控制的,而事务的隔离由数据库系统来管理。
在分布式的高并发环境下,对于核心业务逻辑的检查,要采用加锁机制。使用for update就是一个很好的在分布式环境下的控制手段。
事务常用的两个属性:readonly和timeout,设置事务的超时时间,一般用于防止大事务的发生。还是那句话,事务要尽可能的小!