数据库事务与隔离示例

上传人:re****.1 文档编号:487684055 上传时间:2023-10-13 格式:DOC 页数:10 大小:63.51KB
返回 下载 相关 举报
数据库事务与隔离示例_第1页
第1页 / 共10页
数据库事务与隔离示例_第2页
第2页 / 共10页
数据库事务与隔离示例_第3页
第3页 / 共10页
数据库事务与隔离示例_第4页
第4页 / 共10页
数据库事务与隔离示例_第5页
第5页 / 共10页
点击查看更多>>
资源描述

《数据库事务与隔离示例》由会员分享,可在线阅读,更多相关《数据库事务与隔离示例(10页珍藏版)》请在金锄头文库上搜索。

1、大家都知道,数据库事务的四大特性ACID(Atomic, Consistency, Isolation, Durability),这里主要考虑一致性和隔离性。为了提高事务的处理效率,通常并发的执行多个事务,这就是数据库中非常重要的并发控制。简单 说,并发的执行事务,会有以下问题: 写丢失(Write Lost):比如事务A将x的值更新为10,然后事务A将y的值更新为20,这时A重新读取x发现自己更新过的数据似乎不见了。 脏读(Dirty Read):比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的; 不可重复读(Non-repeatab

2、le 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 accou

3、nt.name=ppgogo*,第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由dd改 成ppgogo1,结果取出来了7个数据。这四种问题呢,有些是可以忍的,有些解决后会大大滴降低并发性。所以,为了适应不同的需求,SQL92,规定了4种隔离级别,隔离级别越高,数据的一致性越好,数据库的并发性越低。 Serializable(全序列化,级别3)提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。 Repeatable Re

4、ad( 可重复读取,级别2)禁止不可重复读取和脏读取,但是有时可能出现幻影数据。这可以通过“共享读锁”和“排他写锁”实现。读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。 Read Committed(授权读取,级别1):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现。读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。 Read Uncommitted(未授权读取,级别0):允许脏读取,但不允许更新丢失。如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。该隔离

5、级别可以通过“排他写锁”实现。l 本示例文档演示SQL SERVER,ORACLE下不同事务隔离级别的区别,以及两种数据库本身的特点l 为了模拟并发环境,SQL SERVER在SMO程序中打开两个查询窗口即可。oracle可以用两个sql *plus程序连接到相同数据库来模拟l SQL SERVER、ORACLE中两个并发用户用事务1,事务2简称。l 所有测试例子,都以最初测试表脚本运行后状态为基准。l 在下列例子中,set transaction isolation level语句会改变会话的隔离级别,直到会话结束。故测试完毕需要改回默认级别。l 最后,但并不是最不重要。以下的演示和相关解释

6、,都是基于易于理解的原则来的,实际的情况可能更复杂,但对开发人员来说,理解如此程度的简化模型已经足够了。测试表脚本:SQL SERVERCREATE 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

7、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)ORACLECREATE TABLE Customer(CustID int NOT NULL,Fname nvarchar2(20),Lname nvarchar2

8、(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, JP, 33045, 5105551212);insert into c

9、ustomer values(3, Jams, bond, ST Geogie 21, Washington, NY, 20331, 4405551864);1。Sqlserver与oracle单条语句处理对比SQL SERVER单条语句默认自动提交,即单条语句自动作为一个事务处理;而oracle的原则是尽量延后提交,除非遇到显式提交命令或者DDL语句。SQL SERVER打开事务1:运行:select * from customer可以看到表有3条记录运行:insert into customer values(4, Hello, world, paradise road 01, heave

10、n, XY, 00001, 1234564321)转到事务2:运行:select * from customer可以看到事务1中刚插入的custid为4的记录。ORACLE打开事务1,运行:select * from customer;可以看到表有3条记录,运行:insert into customer values(4, Hello, world, paradise road 01, heaven, XY, 00001, 1234564321);转到事务2,运行:select * from customer;能看到的还是3条记录,事务1中刚插入的一条记录未自动提交,看不到。转到事务1,运行:

11、commit;转到事务2,运行:select * from customer;现在能看到4条记录了。2. 丢失更新Sqlserver完全兼容ANSI 92标准定义的4个隔离级别。它的默认隔离级别是提交读(read committed),在该级别下,可能会有丢失更新的问题。Oracle的默认情形也一样。故不再重复。SQL SERVER打开事务1运行:set transaction isolation level read committedbegin transelect * from customer-看到3条记录现在切换到事务2,此时事务1还未结束。在事务2中运行:set transacti

12、on isolation level read committedbegin transelect * from customer-看到3条记录,和事务1中相同现在假设事务1事务继续运行,修改数据并提交:update customer set state = TK where CustID = 3commit回到事务2,事务2根据先前查询到的结果修改数据:update customer set Zip = 99999 where state = NYcommit结果因为事务1已经修改了事务2的where条件数据,事务2未成功修改数据(其实准确的说应该算是幻象读引起的更新失败。不过若满足条件的记

13、录数多的话,事务2的update可能更新比预期的数量少的记录数,也可算“丢失”了部分本应完成的更新。个人认为只要明白实际上发生了什么即可,不必过分追究字眼)。丢失更新还可能有别的情形,比如事务2也是update customer set state = KO where CustID = 3两个事务都结束后,事务2的结果反映到数据库中,但事务1的更新丢失了,事务2也不知道自己覆盖了事务1的更新。3脏读演示sqlserver的默认隔离级别是提交读(read committed),当手工将其改为未提交读时,事务可以读取其它事务没提交的数据;oracle由于自身特殊实现机制,可以理解为自身基础的隔离

14、级别就是可重复读(与ANSI标准还是有区别的,后面例子会说明)。SQL SERVER打开事务1,运行:begin transelect * from customerupdate customer set state = TN where CustID = 3转到事务2,运行:set transaction isolation level read uncommittedbegin transelect * from customer此时看到的数据是事务1已经更新但还未提交的(3号记录state值TN)。而如果事务1发觉数据处理有误,转到事务1,进行回滚:Rollback此时事务2如根据刚读取

15、的数据进一步处理,会造成错误。它读取的数据并未更新到数据库,是“脏”的。ORACLEANSI定义未提交读(read uncommitted)级别本意不是为了故意引入错误,而是提供一种可能的最大并发程度级别,即一个事务的数据更新不影响其它事务的读取。Oracle从内核层面实现了更新数据不阻塞读。可以说它提供未提交读级别的兼容,但没有脏读问题。(详情参考对应PPT文档)故oracle没有手工设置read uncommitted级别的语句。4不可重复读Sql server的默认级别没有脏读问题,但存在不可重复读问题。Oracle默认级别也是提交读,不过它因为自身特殊机制,在语句一级不存在不可重复读问题。也就是说当运行时间较长的查询时,查询结果是与查询开始时刻一致的(即使查询过程中其它事务修改了要查询的数据),而SQL SERVER就存在问题(sql server 2005新特

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 机械/制造/汽车 > 汽车技术

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号