数据库事务与隔离示例
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
大家都知道,数据库事务的四大特性ACID(Atomic, Consistency, Isolation, Durability),这里主要考虑一致性和隔离性。为了提高事务的处理效率,通常并发的执行多个事务,这就是数据库中非常重要的‘并发控制’。简单说,并发的执行事务,会有以下问题:
∙写丢失(Write Lost):比如事务A将x的值更新为10,然后事务A将y的值更新为20,这时A重新读取x发现自己更新过的数据似乎不见了。
∙脏读(Dirty Read):比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的;
∙不可重复读(Non-repeatable Read):比如事务A中两处读取数据total的值。
在第一读的时候,total是100,然后事务B就把total的数据改成200,事
务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混
乱。
∙幻象(Phantom Read):和Non-Repeatable Read相似,也是同一个事务中多次读不一致的问题。但是Non-Repeatable Read的不一致是因为他所要取
的数据集被改变了(比如total的数据),但是Phantom Read所要读的数据
的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如
Select account.id where ="ppgogo*",第一次读去了6个符合
条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成
"ppgogo1",结果取出来了7个数据。
这四种问题呢,有些是可以忍的,有些解决后会大大滴降低并发性。所以,为了
适应不同的需求,SQL'92,规定了4种隔离级别,隔离级别越高,数据的一致性越好,数据库的并发性越低。
∙Serializable(全序列化,级别3)提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行
级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不
会被刚执行查询操作的事务访问到。
∙Repeatable Read(可重复读取,级别2)禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取
数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事
务。
∙Read Committed(授权读取,级别1):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许
其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访
问该行。
∙Read Uncommitted(未授权读取,级别0):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写
操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实
现。
●本示例文档演示SQL SERVER,ORACLE下不同事务隔离级别的区别,以及两种数据
库本身的特点
●为了模拟并发环境,SQL SERVER在SMO程序中打开两个查询窗口即可。oracle可以
用两个sql *plus程序连接到相同数据库来模拟
●SQL SERVER、ORACLE中两个并发用户用事务1,事务2简称。
●所有测试例子,都以最初测试表脚本运行后状态为基准。
●在下列例子中,set transaction isolation level语句会改变会话的隔离级别,
直到会话结束。故测试完毕需要改回默认级别。
●最后,但并不是最不重要。以下的演示和相关解释,都是基于易于理解的原则来的,实
际的情况可能更复杂,但对开发人员来说,理解如此程度的简化模型已经足够了。
测试表脚本:
SQL SERVER
CREATE TABLE [Customer](
[CustID] [int] NOT NULL,
[Fname] [nvarchar](20),
[Lname] [nvarchar](20),
[Address] [nvarchar](50),
[City] [nvarchar](20),
[State] [nchar](2) DEFAULT ('CA'),
[Zip] [nchar](5) NOT NULL,
[Phone] [nchar](10)
)
insert into customer values(1, 'Gary', 'Mckee', '111 Main', 'Palm Springs', 'CA', 94312, 7605551212)
insert into customer values(2, 'Tom', 'Smith', '609 Geogia', 'Fresno' 'JP', 33045, 5105551212)
insert into customer values(3, 'Jams', 'bond', 'ST Geogie 21', 'Washington', 'NY', 20331, 4405551864)
ORACLE
CREATE TABLE Customer(
CustID int NOT NULL,
Fname nvarchar2(20),
Lname nvarchar2(20),
Address nvarchar2(50),
City nvarchar2(20),
State nchar(2)DEFAULT'CA',
Zip nchar(5)NOT NULL,
Phone nchar(10)
);
insert into customer values(1,'Gary','Mckee','111 Main','Palm Springs', 'CA', 94312, 7605551212);
insert into customer values(2,'Tom','Smith','609 Geogia','Fresno',