- 论坛徽章:
- 22
|
本帖最后由 will009 于 2015-09-01 14:47 编辑
1、Oracle不支持READ UNCOMMITTED和REPEATABLE READ ,大家觉得有道理吗?
我觉得是有道理的。
READ UNCOMMITTED
这种隔离级别允许脏读(也就是可以读取到用户未提交的数据),支持这种隔离级别的数据库主要是为了支持非阻塞读,但是oracle默认支持非阻塞读,所以oracle里面不支持这种隔离级别。下面举一个例子:
行 帐号 帐户金额(元)
1 123 500.00
2 456 240.25
.. ... ......
342023 987 100.00
假设某一家银行要统计所有账号总共有多少金额。事务A负责统计,事务A从第一行开始读取。假设读取到100行的时候,事务B从账号123转了400元到账户987(事务B还未提交),支持脏读的数据库当事务A读取到342023行的时候,就会得到500元,从而多加了400元。
REPEATABLE READ
这种隔离级别不支持脏读,不支持可重复读,支持幻想读。主要是为了得到一致性的答案与防止丢失更新。
1)得到一致性答案
在oracle里面这个通过多版本机制得到了实现,但是在其他的数据库需要通过加锁机制进行控制,就以上一个例子为例,怎样才能统计出正确的总金额呢,事务A在读取每一行的时候,给每一行加上共享读锁,这样当事务B执行从账号123转400元到账户987的时候。先是操作第一行将账户123的金额由500修改成100,但是第一行已经被事务A锁定,于是等待,这样事务A能够读取到正确的数据。但是如果事务B执行的操作是从账户987转50元到账户123的时候,事务B先操作第342023行,发现没有被锁定,于是锁定将金额由100修改成50,然后操作第一行,发现锁定了于是等待。而事务A读取到342023行的时候,发现这一行已经被事务B锁定于是等待,这样就陷入了死锁。
2)丢失更新
在采用共享读锁的数据库中,这种隔离级别可以防止丢失更新,比如事务1先读取了第A行然后修改了这一行的C列(其他列也修改了只是值还和以前一样,因为程序员都是整行的更新)。这个时候事务2想也想修改A行的时候会被阻塞,防止事务1的更新被覆盖。
2、默认事务隔离级别,大家认为使用四种隔离级别哪一种隔离级别作为默认事务隔离级别是最好的,好在哪,其他的隔离级别差在哪?
默认事务隔离级别,我觉得Read Commited作为默认事务隔离级别是最好的。事务管理是数据库处理的核心,数据库既要保证用户能并发地执行事务,还要保证数据库的一致性。事务隔离程度越高,并发性越差、性能越低;事务隔离程度越低,并发性越强、性能越高。
Read Commited :读已提交数据。这是Oracle的默认隔离级别,查询语句只能看到已提交的数据。隔离的已提交读能保证在访问特定的行时,该行的数据保持不变。所以,这个级别可以防止脏读和更新丢失。
数据库并发的事务会带来以下四个问题:脏读,更新丢失,不可重复读,幻读。
Read Uncommited (读未提交数据)虽然并发性最高,但会出现脏读,不可重复读,幻读,更新丢失。
Repeatable Read (可重复读)会出现幻读。
Serializable (可串行化)隔离级别最高,但数据库的并发性受到了很大的限制。对DML操作的数据会放置一个写锁,别的涉及DML的操作不得不等待锁解除。可以避免上面的四个问题,但在现实中不可用。
3、事务隔离级别越高,性能越差这个观点虽然在《Transaction Processing》书中说性能相差不大,但是实际上在数据库实现上持有锁的时间是增加了的,持有锁的时间增加意味着并发的降低,大家是认同《Transaction Processing》书中的观点吗,请说出认同或者不认同的理由。
不认同。事务隔离级别越高,越能保证数据的一致性,但对并发性能影响越大,一致性和高性能必须有所取舍或折中。一般情况下,多数应用程序可以选择将数据库的隔离级别设置为读已提交,这样可以避免脏读,也可以得到不错的并发性能。尽管这个隔离级别会导致不可重复读、幻读,但这种个别场合应用程序可以通过主动加锁进行并发控制。
事务隔离级别是并发控制的整体解决方案,其实际上是综合利用各种类型的锁和行版本控制,来解决并发问题。锁是数据库并发控制的内部机制,是基础。当然,数据库同时还会利用行版本控制(SQL Server 2005 及以上)来进行并发控制;在数据库内部还使用闩(latch),互斥(mutex)等机制处理内部资源(如,缓存)的并发访问。
对用户来说,只有当事务隔离级别无法解决一些并发问题和需求时,才有必要在语句中手动设置锁。不适当的设置锁,可能会导致严重的阻塞和死锁。建议,只有在完全了解锁机制的情况下,才可以在语句中手动设置锁,否则应该使用事务隔离级别。
4、数据库是否需要学SQL Server提供一个打开和关闭MVCC的开关,让用户自己决定是否使用MVCC,进而让用户来承担MVCC所带来的副作用的风险,而不是默认只能用MVCC。
可以参考吧
Oracle、MySQL和SQL Server都有MVCC,只是实现方式不大相同,用户可以综合考虑整体性能,折衷取舍。关系数据库管理系统使用MVCC(Multiversion Concurrency Control多版本并发控制)来避免写操作堵塞读操作的并发问题,MVCC也就是通过使用数据的多个版本保证并发读写不冲突的一种机制,不同的数据库有不同的实现,这也是数据库系统让人头疼的地方,关系数据库表面看上去很简单方便,使用标准的SQL语句操作让人很放心,但是随着系统规模增加,并发用户增加,数据库会出现性能降低的现象,这时我们可能需要从外
部的微调进入到内部原理的深入研究,而每个数据库内部实现并发的原理都是不同的,如果我们拥有多个不同的数据库,那么需要不同的调校方法。
MVCC的两种不同实现方式
第一种实现方式是将数据记录的多个版本保存在数据库中,当这些不同版本数据不再需要时,垃圾收集器回收这些记录。这个方式被PostgreSQL和Firebird/Interbase采用,SQL Server使用的类似机制,所不同的是旧版本数据不是保存在数据库中,而保存在不同于主数据库的另外一个数据库tempdb中。
第二种实现方式只在数据库保存最新版本的数据,但是会在使用undo时动态重构旧版本数据,这种方式被Oracle和MySQL/InnoDB使用。
|
|