前几天同事讲了Transaction isolation level,并且大家一起在SQLServer,Oracle跟MySQL数据库上实验了一下,发觉这些知识还是挺重要的。
假如有两个事务并发,顺序如下
Transaction A Transaction B
begin begin
query1 from table A
....... modify1 to table A(insert/update/delete)
commit
query2 from table A
commit
那么在事务A中,query1跟query2查询出来的结果是否一样呢?这就跟事务隔离级别有关了。
SQL的标准定义里面,一共有四种级别:
read uncommited读取未提交的数据 就是其他事务求提交的数据,都可以读取出来
read commited读取已提交的数据 query2会跟query1读取的数据不一样
repeatable read可重复读取,即query1跟query2读取的数据是一样的
serializable 序列化,
SQL 标准用三个必须在并行的事务之间避免的现象定义了四个级别的事务隔离。 这些不希望发生的现象是:
脏读(dirty reads)
一个事务读取了另一个未提交的并行事务写的数据。
不可重复读(non-repeatable reads)
一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过。
幻读(phantom read)
一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最近提交的事务而发生了改变。
隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read)
读未提交(Read uncommitted) 可能 可能 可能
读已提交(Read committed) 不可能 可能 可能
可重复读(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
SQLServer
我们首先在SQLServer上做了实验,SQLServer一共支持四种隔离级别,read uncommited跟read commited我们没有实验,我们直接先实验
repeatable read,如果事务A定义了如下级别,那么当事务B执行到modify1这条语句时,如果modify1是update的话,就被锁起来,一直等
到事务A提交完以后,锁才会被释放,而如果是insert的话,刚可以顺利进行下去,然后在事务A中,query2查到的数据,是已经被事务B
修改过的数据,如果将级别定义在serializable的话,则在modify1语句中,update,insert或者delete都会被锁掉。
也就是说,SQLServer对这些级别的支持,是通过锁来做到的,虽然可以保证事务正常进行,但是并行的性能却很差。
Oracle
oracle只支持两个级别,read commited跟serializable,结果这里就不用详细说明,实验的结果是,oracle的serializable是通过版本
控制来完成的,而不是通过锁机制,这就保证了并行的性能。Oracle的默认级别是read commited
MySQL
MySQLServer也支持四个级别,而且MySQL也是通过版本控制而非锁机制来完成的。
文章来源:
http://blog.csdn.net/Wingel/archive/2006/11/26/1414839.aspx