赞
踩
mysql引入事务的目的是为了保证数据操作的一致性,有了事务之后,用户可以把一组操作定义为原子性的操作。mysql的事务具有ACID的特性。
隔离性(isolation):其表明的是事务与事务之间的可见性,其中事务被定义了四种隔离级别,未提交读、提交读、可重复读、串行化。其中mysql默认隔离级别可重复读,其保证事务中的读取操作在任何时间段读取的结果都是一样的,并且不会受其他事务的影响(提交或者未提交)。
在我们具体介绍事务的这四个特性之前还需要介绍下mysql中锁的概念。其中锁在是否加锁的上分为乐观锁和悲观锁,其中乐观锁是一种通过多版本控制的方式来实现类似加锁的操作,其本质上是每次对数据的更新都会改变数据的版本,并且在回写的时候回检查当前版本是不是修改之前的版本,如果不是证明已经有其他程序更改过该数据,这样的回写操作会失败。如此来保证了数据的一致性。其中mvcc就是mysql的乐观锁实现。悲观锁则是需要在数据上进行加锁从而来保证数据的一致性,其中有根据锁的并发粒度分为共享锁(读锁)和互斥锁(写锁)。共享锁是指所有的读操作都能共享的使用同一锁从而提高读锁的并发度。互斥锁是指所有的所有加了互斥锁的数据,不能能够再加读锁和写锁,使得需要加锁的读和写操作都要等待该互斥锁的释放。在mysql中是通过悲观锁来解决幻读的问题。
mysql实现原子性操作是同对每个一个事务的操作都记录一个undo log,当事务执行失败时,通过undo log来回滚到事务的初始状态。同时由于事务的隔离性保证了这样的回滚操作不会影响其他的事务,因为其他事务还是读取该事务开始时的数据。对于写操作会加互斥锁,因此通过undo log回滚到事务的开始状态也不会出现数据覆盖导致变更丢失的危险。
Undo Log的原理很简单,为了满足事务的原子性,在操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之前的状态。
用Undo Log实现原子性和持久化的事务的简化过程:假设有A、B两个数据,值分别为1,2。
这里有一个隐含的前提条件:‘数据都是先读到内存中,然后修改内存中的数据,最后将数据写回磁盘’。之所以能同时保证原子性和持久化,是因为以下特点:
其实如果按照上述undo的方式进行实现那么数据的持久性已经得到保证了,但是其有一个很大的缺点:每个事务提交前将数据和Undo Log写入磁盘,这样会导致大量的磁盘IO,因此性能很低。并且根据2-8原理该写入的数据很快的会重新被读取出来,如果需要每次把变更的数据写入硬盘之后,再进行读取,不仅吞吐量低,并且磁盘IO会成倍数增加。因此如果能够将数据缓存一段时间,就能减少IO提高性能。但是这样就会丧失事务的持久性,事务提交了但是数据并没有写入磁盘,如果系统崩溃就会操作数据的丢失。因此引入了另外一种机制来实现持久化,即Redo Log.
和Undo Log相反,Redo Log记录的是新数据的备份。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是Redo Log已经持久化。系统可以根据Redo Log的内容,将所有数据恢复到最新的状态。
Undo + Redo事务的简化过程:假设有A、B两个数据,值分别为1,2.
Undo + Redo事务的特点
数据恢复策略:
mysql的默认隔离级别为可重复读,其实现方式是MVCC(多版本控制)。mvcc的主要作用是保证同一个事务的多次的同一个读操作前后两次读的结果是一致的,其原理是在事务中第一次读取时会记录数据库中记录的版本,即使另外一个事务对数据进行更改并已提交,在后续读取时依然是以前版本的数据,不是最新版本,其类似于快照数据,因此对于事务中的读取操作都是快照读,并且事务之间的中间结果是互相不可见的。注意:没有事务的读取操作是读取的最新版本的数据,没有隔离性。对于在事务中(select * from xxx lock in share mode 或者 select * from xxx for update)会申请加锁,因此对于后续需要修改的操作都会被阻塞。因此对于需要加锁的操作读取的都是最新的数据,又叫当前读(当前版本对应于快照读)。多版本控制就是指在数据库中同时存在多个版本的数据,正式由于多版本控制保证了mysql的事务隔离级别为可重复读。
由于事务的原子性和隔离性保证了数据只会从一个一致性状态变到另外一个一致性。因此原子性保证一个事务的一组操作只会同时成功或者同时失败,再加上数据的隔离性保证了事务间的一组操作的中间结果是不可见的。从而最终保证了数据的一致性。
什么是幻读:http://blog.csdn.net/cweeyii/article/details/70991230
何登成mysql博客:http://hedengcheng.com/?p=771
在mysql事务中根据是否加锁可以分为两类操作:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。