并发控制机制试图在多个事务中交叉(同时)执行Read和Write操作,并使得交叉执行的结果与串行调度执行的结果一样。这个交叉执行给人的感觉是事务在并行执行。并发控制非常重要,因为事务在共享数据库上的同时执行可能会产生若干数据完整性和一致性的问题。
并发控制问题
当并发事务以不受控制的方式执行时,可能会出现一些问题。并发控制主要有下述三个问题:
丢失更新(也称幻像读)
脏读
不可重复读
丢失更新:当两个事务访问相同的数据库项时就会出现丢失更新的问题,使得某些数据库项的值会不正确。换句话说,如果事务T1和T2都是先读一条记录,然后进行修改,那么第一个更改的影响将被第二个更改所覆盖。
脏读:当一个事务修改数据库项,却由于某些原因使得事务失败了,而被修改的数据库项在被修改回原来的原始值之前又被其他的事务访问了,这时就会出现脏读的问题。换句话说,事务T1修改一个记录,而这个记录正被事务T2读取,然后T1异常终止了,而T2现在有一个不是稳定的数据库的值。
不可重复读:当某个事务在一些数据集上计算一些汇总(聚合)函数,而其他的事务正在修改这些数据时就会出现不可重复读(或不一致检索)问题。这个问题是事务可能在一些数据被更改之前读取而另一些数据是在被更改后读取,因此产生了不一致的结果。在不可重复读中,事务T1读取一个记录,然后在事务T2更改这个记录时进行一些其他的处理。现在,如果T1重新读取这个记录,则新的值将和之前的值不一致。
事务的隔离级别
为了解决上述的三个并发控制的问题 ,数据库划分了四个事务隔离级别:
Read Uncommitted(读取未提交隔离级别):读数据时不加锁,允许脏读、不可重复读、幻读。
Read Committed(读取提交隔离级别):在读数据之前加一个读锁,读完之后释放锁。允许不可重复读、幻读。
Repeatable Read(可重复读取隔离级别):在读数据之前加一个读锁,读完之后不释放锁,直到事务rollback或者commit后才释放锁。允许幻读。
Serializable(串行化读取隔离级别):在读数据之前在读取的条件上加锁(称为条件锁),读完之后不释放锁,直到事务rollback或者commit后才释放锁。不允许脏读、不可重复读、幻读。
oracle与mysql默认的事务隔离级别
oracle数据库只支持Read committed和Serializable这两种事务隔离级别,所以oracle不支持脏读。oracle默认使用的隔离级别是:读取提交隔离级别(Read Committed)。
mysql支持这四种隔离级别,但默认的隔离级别是:可重复读取隔离级别(Repeatable Read)。