RMDB中的事务隔离级别

点击量:445

网上关于这部分的介绍很多,这里写下自己对这几个隔离级别的理解。
首先解释下什么是隔离性(isolation):DB中的隔离性指的是一个操作产生的影响什么时候以哪种方式可以对其他并发操作可见。

然后再介绍几个容易混淆的概念:幻读,脏读和不可重复读
脏读(dirty reads)
某一个事务读取了另一个事务中已经修改了的但是尚未commit的数据,这就是脏读。一旦另一个事务发生回滚,则读取的值就是脏读了。
幻读(phantom reads):
A phantom read occurs when, in the course of a transaction, two identical queries are executed, and the collection of rows returned by the second query is different from the first.
在一个事务中,两个同样的查询语句得到的查询结果却不一样,这就是幻读,这里要注意一点:幻读是针对多条返回结果而言的
不可重复读(non-repeatable read)
A non-repeatable read occurs, when during the course of a transaction, a row is retrieved twice and the values within the row differ between reads.
这里指的是同一条记录在同一个事务中两次读取的结果是不一样的。这里指的是同一条记录。

四种隔离级别
Read uncommitted
字面意思就是一个事务可以读取另一个事务还未提交的记录,很显然这种级别的隔离是不推荐使用的,因为会导致dirty reads即脏读。
Read committed
这个隔离级别可以理解为“always read committed row”,总是读取已经提交的记录。举个例子,你在事务1中读取一条数据,然后在事务2中更新这条数据,然后再在事务1中用同一句SQL语句查询这条数据,得到的数据是事务2中刚刚提交的数据。这是很多数据库默认使用的隔离级别,比如SQLServer但是MySQL使用的却是可重复读,下面会讲到。那么这个隔离级别具体是怎么实现的呢?数据库对查询的数据集做写锁(write lock)时会一直保持这个锁直到这个事务提交结束,也就是说选定范围的数据不能被修改。而这个结果集上的读锁(read lock)却在查询结束之后就立即被释放了,所以其他事务会对这个结果进行修改,这样会导致不可重复读取。此外,这个级别的事务隔离没有提供范围锁(range-locks),虽然对结果集加了锁,但是对查询范围却没有加锁,这就会导致我们之前提到的幻读。比如事务1查询的范围是id在1-50之间的数据,而同时事务2却新插入了一个id=20的数据,然后事务1再读取的时候发现两次的结果集不一样了,这就造成了幻读。由此可见,Read committed会导致不可重复读,幻读,但不会脏读。
Repeatable reads
可重复读的实现是数据库对结果集的读写锁都会保持到事务结束,所以这能保证同一条记录两次读取的值是相同的。但是跟Read committed一样,这种方式没有提供范围锁(range-locks),所以也会导致幻读。
Serializable
这是最高的隔离级别,读写锁会一直持续到事务结束,同时他也提供了范围锁。正因为这样,导致他的并发效率不是很高,因此在实际生产环境中很少使用。

最后总结一下这几个隔离级别对几种读现象的表现:

isolation

参考:
wikipedia-isolation
stackoverlow-questions-11043712
blog.9minutesnooze.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注