什么是事务
事务提供一种机制,能够将一个流动波及的所有操作纳入到一个不可分割的执行单元,组成事务的所有操作只有在所有操作均能失常执行的状况下方能提交,只有其中任一操作执行失败,都将导致整个事务的回滚。简略地说,事务提供一种“要么什么都不做,要么做全套(All or Nothing)机制。
如果A要给B转账1000元,这个转账会波及到两个要害操作就是:将A的余额缩小1000元,将B的余额减少1000元。事务就是保障这两个要害操作要么都胜利,要么都要失败。
ACID
事务应该具备4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID个性。
原子性(Atomicity):原子性是指单个事务自身波及到的数据库操作,要么全副胜利,要么全副失败,不存在实现事务中一部分操作的可能。
以上文说的转账为例,就是要么操作全副胜利,A的钱少了,B的钱多了;要么就是全副失败,AB放弃和原来一样的数目。
一致性(Consistency):一致性就是事务执行前后的数据状态是稳固的。还是以转账为例,原来AB账户的钱加一起是1000,互相转账实现时候彼此还是1000,所以,对于转账就是金额稳固不变,对于其余的事务操作就是事务执行实现之后,数据库的状态是正确的,没有脏数据。
隔离性(isolation):一个事务的执行不能被其余事务烦扰。也就是说多个事务之间是没有相互影响的比方A给B转账和B给C转账这两个事务是没有影响的。
持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的扭转就应该是永久性的。
事务的隔离级别
在多个事务并发操作数据库(多线程、网络并发等)的时候,如果没有无效的防止机制,就会呈现脏读、不可反复读和幻读这3种问题。
脏读(Dirty Read)
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
不可反复读(Nonrepeatable Read)
不可反复读是指在对于数据库中的某个数据,一个事务范畴内屡次查问却返回了不同的数据值,这是因为在查问距离,被另一个事务批改并提交了。
幻读(Phantom Read)
一个事务内前后屡次读取,数据总量不统一。
不可反复读和幻读有些类似,两者的区别在于:不可反复读的重点在于批改,同样的条件, 你读取过的数据,再次读取进去发现值不一样了;而幻读的重点在于新增或者删除对幻读的定义,记录的缩小也应该算是幻读),同样的条件, 第 1 次和第 2 次读出来的记录数不一样。
隔离级别
读未提交(Read Uncommitted):一个事务能够读取到另一个事务未提交的批改。这种隔离级别是最弱的,可能会产生脏读,幻读,不可反复读的问题问题。
读已提交(Read Committed):一个事务只能读取另一个事务曾经提交的批改。其防止了脏读,依然存在不能够反复读和幻读的问题。SQL Server和Oracle的默认隔离级别就是这个。
可反复读(Repeated Read):同一个事务中屡次读取雷同的数据返回的后果是一样的。其防止了脏读和不可反复读问题,然而幻读仍然存在。MySQL中的默认隔离级别就是这个,不过MySQL通过多版本并发管制(MVCC)、Next-key Lock等技术解决了幻读问题。
串行化(Serializable):这是数据库最高的隔离级别,这种级别下,事务“串行化程序执行”,也就是一个一个排队执行。在这种级别下,脏读、不可反复读、幻读都能够被防止,然而执行效率奇差,性能开销也最大。
MySQL是如何解决幻读
可反复读的隔离级别没有方法彻底的解决幻读的问题,如果须要解决幻读的话也有两个方法:
1.应用串行化读的隔离级别
2.MVCC+next-key locks:next-key locks由record locks(索引加锁) 和 gap locks(间隙锁,每次锁住的不光是须要应用的数据,还会锁住这些数据左近的数据)
快照读
当执行select操作是innodb默认会执行快照读,会记录下这次select后的后果,之后select 的时候就会返回这次快照的数据,即便其余事务提交了不会影响以后select的数据,这就实现了可反复读了。
以后读
对于会对数据批改的操作(update、insert、delete)都是采纳以后读的模式。在执行这几个操作时会读取最新的记录,即便是别的事务提交的数据也能够查问到。假如要update一条记录,然而在另一个事务中曾经delete掉这条数据并且commit了,如果update就会产生抵触,所以在update的时候须要晓得最新的数据。
MVCC仅能解决快照读状况下,也就是select查问的时候的幻读问题。对于以后读状况下,也就是update、insert、delete等操作时产生幻读问题MVCC无奈解决,须要应用临键锁也就是next-key locks解决