为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

南京二氧化锆烤瓷牙.doc

2017-09-02 30页 doc 65KB 21阅读

用户头像

is_597436

暂无简介

举报
南京二氧化锆烤瓷牙.doc南京二氧化锆烤瓷牙.doc 第 6 部分: 数据并发性 简介: 本教程是共包含 9 篇教程的第 6 篇,这个 系列教程 旨在帮助您熟悉 IBM? Informix? Dynamic Server(IDS)的所有方面,以及帮助您准备 IDS 基础认证考试(555)。本教程与考试的第 6 部分对应,您将从中理解到 IDS 中的数据并发性机制。 关于本系列 这个共包含 9 个部分的免费 系列 将帮助您准备 IBM Informix Dynamic Server 11.50 基础认证考试 555。这个认证将考察关于 IDS ...
南京二氧化锆烤瓷牙.doc
南京二氧化锆烤瓷牙.doc 第 6 部分: 数据并发性 简介: 本是共包含 9 篇教程的第 6 篇,这个 系列教程 旨在帮助您熟悉 IBM? Informix? Dynamic Server(IDS)的所有方面,以及帮助您准备 IDS 基础认证考试(555)。本教程与考试的第 6 部分对应,您将从中理解到 IDS 中的数据并发性机制。 关于本系列 这个共包含 9 个部分的免费 系列 将帮助您准备 IBM Informix Dynamic Server 11.50 基础认证考试 555。这个认证将考察关于 IDS 11.50 管理的入门级知识,包括基础 SQL、如何安装 IDS 11.50、如何创建数据库和数据库对象、安全性、事务隔离、备份和恢复,以及数据复制技术。这些教程为考试的每部分打下了坚实的基础。不过,您不能仅使用这些教程作为唯一的考试准备。 理解锁 什么是锁, 锁 是一种软件机制,用于控制对数据库中的数据的访问。在出现同时读取和更新数据的多用户环境中,锁能够确保每个事务的原子性、隔离、一致性和持续性(ACID)不受到威胁,并且维护数据的完整性。 锁的粒度 Informix 提供各种粒度的锁。它们是: , 数据库锁:针对整个数据库的锁 , 表锁:针对整个表的锁 , 页锁:针对整页数据的锁 , 行锁:针对一个数据行的锁 , 字节锁:在包含 VARCHAR 的行上的锁 , 键锁:在索引中的一个键值上的锁 锁的粒度越粗,它就能锁住越多的数据库对象。例如,对于能够在一个磁盘页上包含 4 行的表,在该页放置一个锁将锁住其中包含的所有 4 个行。相反,如果使用行锁,那么将仅锁住一个行。因此,锁的粒度越粗,并发性就越低,从而影响到性能,尤其是应用程序试图访问相同的行集时。不过,粗粒度也意味着在某些情况下锁住相同数量的行需要的锁数量更少。例如,锁住整个表仅需要一个表锁。 回页首 表的锁模式 创建一个表时,它的默认锁粒度是页锁。可以在创建表的过程中使用 LOCK MODE 子句覆盖默认值。例如: CREATE TABLE t1(c1 int) LOCK MODE ROW; 这个上下文中的锁模式表明访问表时需要使用的锁的粒度。如果从 CREATE SQL 语句省略掉这个 LOCK MODE 子句,那么就使用默认的锁模式。 如果表已经创建,那么可以使用 ALTER TABLE 语句更改锁模式。对于以上提到的表 t1 例子,您可以使用下面的 ALTER 语句将锁模式从行锁更改页锁: dbaccess db1 - ALTER TABLE t1 LOCK MODE(PAGE); 可以使用配置参数 DEF_TABLE_LOCKMODE 更改已创建的表的默认锁模式。该参数的值可以是 ROW 或 PAGE。例如,如果 DEF_TABLE_LOCKMODE 设置为 ROW,那么数据库服务器重启之后创建的表的默认锁模式将为 ROW。 类似地,可以使用环境变量 IFX_DEF_TABLE_LOCKMODE 实现相同的效果。注意:如果从运行 oninit 以启动服务器的窗口设置环境变量,那么通过环境变量指定的默认锁模式将对所有会话有效。然而,如果仅在特定客户端会话环境中设置锁模式,那么它仅对特定会话有效。 清单 1 - 4 显示了检查表的锁模式的不同方法(表名为 t1;数据库名为 db1): 清单 1. 使用 dbschema dbschema -d db1 -t t1 -ss 清单 2. 输出 create table "informix".t1 ( c1 integer ) extent size 16 next size 16 lock mode row; 清单 3. 使用 oncheck oncheck -pt db1:t1 Output: TBLspace Report for db1:informix.t1 Physical Address 1:64070 Creation date 07/14/2009 04:51:27 TBLspace Flags 802 Row Locking TBLspace use 4 bit bit-maps Maximum row size 4 Number of special columns 0 Number of keys 0 Number of extents 1 Current serial value 1 Current SERIAL8 value 1 Current BIGSERIAL value 1 Current REFID value 1 Pagesize (k) 2 First extent size 8 Next extent size 8 Number of pages allocated 8 Number of pages used 1 Number of data pages 0 Number of rows 0 Partition partnum 1049067 Partition lockid 1049067 Extents Logical Page Physical Page Size Physical Pages 0 1:64999 8 8 清单 4. 使用 dbaccess 从数据库的系统目录表查询系统表 dbaccess db1 - > select * from systables where tabname='t1'; tabname t1 owner informix partnum 1049067 tabid 100 rowsize 4 ncols 1 nindexes 0 nrows 0.00 created 07/14/2009 version 6553601 tabtype T locklevel R npused 0.00 fextsize 16 nextsize 16 flags 0 site dbname type_xid 0 am_id 0 pagesize 2048 ustlowts secpolicyid 0 protgranularity 字段 “locklevel” 为 R,表明这是一个行锁。 另外,使用 onstat -k 来监控锁模式。这将在 “使用 onstat 实用程序监控锁” 小节进行介绍。 回页首 锁的类型 数据库、表、页和行(在这个小节中统称为对象)通过不同类型的锁来控制对自 身的访问。IDS 使用以下类型的锁: 共享锁 当需要读取数据并且不允许更改行时,那么就可以在该对象(比如表、页或行) 上设置一个共享锁。一个对象可以由不同的会话设置多个共享锁。因此,可以在 需要时在一个对象上设置多个共享锁。 更新/提升锁 可以在需要更新的对象上设置更新锁。如果一个对象已经设置了共享锁,另一个会话还可以在其上设置一个更新锁。如果需要更改对象,那么更新锁必须提升为独占锁。不过,为了实现独占锁,在提升过程中该对象不能包含共享锁或更新锁。 独占锁 当一个会话请求单独使用某个对象时,可以在该对象上放置一个独占锁。如果一个对象上已经放置了独占锁,那么其他会话就不能再在该对象上放置其他类型的锁。 INSERT、UPDATE 和 DELETE 语句在它们所更改的行上使用这个锁。在事务完成之后将释放该锁。 onstat 实用程序和 syslocks 表使用以下符号表示锁的类型: , 共享锁 - S , 更新锁 - U , 独占锁 - X 在某些情况下,可以通过放置一个意向锁(intent lock)来表明要放置特定锁的意向。例如,意向共享锁的表示符号为 IS。在使用 SELECT 语句期间通常可以在表上看到 IS 锁。在使用 INSERT、UPDATE 或 DELETE 语句期间通常可以在表上看到意向独占锁。 表 1 使用这些符号列出了一个兼容性矩阵,显示当一个会话已经在某个对象上放置了特定的锁时,另一个会话可以在该对象上请求的锁。 表 1. 锁兼容性矩阵 持有 X 持有 U 持有 S 持有 IS 持有 持有 IX 锁 锁 锁 锁 SIX 锁 锁 请求 X No No No No No No 锁 请求 U No No Yes Yes No No 锁 请求 S No Yes Yes Yes No No 锁 请求 IS No Yes Yes Yes Yes Yes 锁 请求 No No No Yes No No SIX 锁 请求 IX No No No Yes No Yes 锁 回页首 锁请求失败 当会话请求锁失败时,数据库服务器的默认行为是返回一个错误。要让该会话等 待拥有锁的会话释放锁,请在运行预定语句之前运行以下 SQL 语句: SET LOCK MODE TO WAIT; 这将让会话一直等到锁释放。如果要设置固定的等待期限(例如,5 秒),则使 用以下语句: SET LOCK MODE TO WAIT 5; 回到默认行为: SET LOCK MODE TO NOT WAIT; SET LOCK MODE 语句仅在会话级别有效。 我们通过以下例子查看锁模式的行为: 清单 5. 开始会话 dbaccess - - DROP DATABASE db1; CREATE DATABASE db1 WITH BUFFERED LOG; CREATE TABLE t1 (c1 int); INSERT INTO t1 VALUES (1); 清单 6. 会话 A dbaccess db1 - BEGIN WORK; UPDATE t1 SET c1=5; 清单 7. 会话 B dbaccess db1 - SELECT* FROM t1; 清单 8. 收到的错误 244: Could not do a physical-order read to fetch next row. 107: ISAM error: record is locked. 清单 9. onstat -g sql 输出 $ onstat -g sql IBM Informix Dynamic Server Version 11.50.FC4 -- On-Line -- Up 1 days 06:16:34 -- 149504 Kbytes Sess SQL Current Iso Lock SQL ISAM F.E. Id Stmt type Database Lvl Mode ERR ERR Vers Explain 30 - db1 CR Not Wait 0 0 9.24 Off 输出结果显示 db1 的隔离级别为 “Committed Read”(后面将讨论隔离级别)。因为表 t1 上有一个未提交的更新,错误提示需要使用锁定的记录。 让我们在会话 B 中尝试使用 SET LOCK MODE WAIT 语句: SET LOCK MODE TO WAIT; SELECT* FROM t1; 这个会话并没有立即返回错误,而是等待锁释放。 现在,在会话 A 中,完成事务: COMMIT WORK; 在会话 B 中,现在是等待提交结束之后才返回查询结果。 死锁 当两个会话都持有它们需要使用的锁时就会导致死锁。结果是两个会话都等待对方释放锁。不过,数据库服务器可以检测到这种情况并阻止它发生。例如: T1:读取行 A 并在其上放置一个锁。 T2:读取行 B 并在其上放置一个锁。 T1:在行 B 上请求一个锁。 T2:在行 A 上请求一个锁。 IDS 维护一个内部锁表。为了防止出现死锁,IDS 将检查内部锁表,查看在会话等待锁期间是否会导致死锁。发生的情况如下所示: T1:将锁模式设置为等待。 T2:将锁模式设置为等待。 T1:读取行 A 并在其上放置一个锁。 T2:读取行 B 并在其上放置一个锁。 T1:在行 B 上请求一个锁;必须等待 T2 在行 B 上释放该锁。 T2:在行 A 上请求一个锁,但被拒绝了,因为等待该锁的释放会导致死锁。 IDS 从内部锁表检测到: , T1 持有行 A 上的锁 , T2 持有行 B 上的锁 , T1 等待 T2 持有的行 B 上的锁 如果允许 T2 等待 T1 在行 A 上持有的锁,那么将出现死锁。因此,锁请求被拒绝,并返回错误 (-143 ISAM error: deadlock detected)。 检查 onstat -p 的输出看看是否有死锁: 清单 10. 检查 onstat -p 输出中的死锁 $ onstat -p IBM Informix Dynamic Server Version 11.50.FC4 -- On-Line -- Up 2 days 22:34:37 -- 157696 Kbytes Profile dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits %cached 13851 44301 1894394 99.27 22604 41159 429311 94.73 isamtot open start read write rewrite delete commit rollbk 1178884 64495 88313 413795 46723 58450 5657 17833 16 gp_read gp_write gp_rewrt gp_del gp_alloc gp_free gp_curs 0 0 0 0 0 0 0 ovlock ovuserthread ovbuff usercpu syscpu numckpts flushes 0 0 0 89.23 13.32 366 70849 bufwaits lokwaits lockreqs deadlks dltouts ckpwaits compress seqscans 191 0 750183 5 0 6 4010 6770 ixda-RA idx-RA da-RA RA-pgsused lchwaits 231 2 3080 3313 254 查看 “deadlks” 字段,您可以看到在数据库服务器上线至今发生了 5 个死锁 事件。如果频繁发生死锁,请检查应用程序并交错使用频繁更改的行。通过减少 锁等待时间可以降低出现死锁的几率。 对于分布式事务,会话在返回错误之前使用 DEADLOCK_TIMEOUT 配置参数等待来 自远程数据库的响应。在 onstat -p 输出中的 “dlouts” 字段显示分布式死 锁超时的统计数据。 日志和非日志数据库 在日志数据库中,数据库服务器记录其事务以及在事务期间持有的锁。一般都能 够识别到事务持有的锁,除非事务没有提交或被回滚。非日志数据库中没有事务, 但仍然使用锁。尽管很容易错过,但是服务器在执行 Data Manipulation Language 时使用锁,并且在该语句完成之后快速释放锁。 监控锁 onstat 实用程序监控锁 数据库服务器使用的锁保持在一个内部锁表中。使用 onstat -k 命令可以监控 数据库服务器持有的锁的类型和粒度。 onstat -k 命令的输出包含以下字段: 表 2. onstat -k 命令输出包含的字段 字段 说明 锁表中的锁的位置。如果用户线程正在等待这address 个锁,那么该锁的地址就会出现在 onstat -u (用户)输出的 wait 字段中。 等待锁的用户线程列表的第一项,如果存在的wtlist 话。 持有锁的线程的共享内存地址。这个地址与 onstat -u(用户)输出中的 address 字段中 的地址对应。当持有者值显示在圆括号中时,owner 它表示事务结构的共享内存地址。仅当为全局 事务分配锁时才会发生这种情况。这个地址与 onstat -G 输出的 address 字段对应。 刚才列出的持有者持有的链接锁列表中的下lklist 一个锁。 使用以下符号表示锁的类型: , HDR - 头部 , B - 字节 , S - 共享 , X - 独占 type , I - 意向 , U - 更新 , IX - 意向独占 , IS - 意向共享 , SIX - 共享意向独占 行标识号码。rowid 提供以下锁信息: , 如果 rowid 为 0,那么这个锁是一个 表锁。 , 如果 rowid 以两个 0 结尾,那么这个 锁是一个页锁。 tblsnum , 如果 rowid 小于等于 6 位数并且不 以 0 结尾,那么这个锁可能是一个行 锁。 , 如果 rowid 大于 6 位数,那么该锁可 能是一个索引键-值锁。 索引键值号,或为 VARCHAR 锁锁定的字节数。 如果这个字段包含 “K-” 并且其后接一个key#/bsiz值,那么这是一个键锁。该值标识要锁住的索 引。例如,K-1 表示为表定义的第一个索引包 含一个锁。 回页首 onstat -k 命令的示例输出 这个例子使用不遵从 ANSI 的日志数据库和两个表: CREATE DATABASE db1 WITH LOG; CREATE TABLE t1 (c1 int); CREATE TABLE t2 (c1 int) LOCK MODE ROW; 以下值被插入到这两个表中: INSERT INTO t1 VALUES (1); INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (2); 执行以下语句: BEGIN WORK; UPDATE t1 SET c1=5; UPDATE t2 SET c1=5; onstat -k 的输出: 清单 11. onstat -k 的输出 $ onstat -k IBM Informix Dynamic Server Version 11.50.FC4 -- On-Line -- Up 2 days 21:39:44 -- 157696 Kbytes Locks address wtlist owner lklist type tblsnum rowid key#/bsiz 10a3134d8 0 111535cd8 0 HDR+S 100002 204 0 10a44bcd8 0 111535488 0 S 100002 204 0 10a44bd58 0 111536528 0 S 100002 204 0 10a44c4d8 0 111537e18 0 HDR+S 100002 202 0 11348b028 0 111537e18 10a44c4d8 HDR+IX 1001ef 0 0 11348b0a8 0 111537e18 11348b028 HDR+X 1001ef 100 0 11348b128 0 111537e18 11348b0a8 HDR+IX 1001f0 0 0 11348b2a8 0 111537e18 11348b128 HDR+X 1001f0 101 0 U 11348b328 0 111537e18 11348b2a8 HDR+X 1001f0 102 0 U 9 active, 80000 total, 16384 hash buckets, 2 lock table overflows 该输出包含以下信息: , 表锁: o 查看地址为 11348b028 的行,其 rowid 为 0,表明这个锁是表锁。 IX 表明其类型为意向独占。 , 页锁: o 查看地址为 11348b0a8 的行,其 rowid 的最后两位为 00,表明 这个锁是页锁。类型 X 表明它是独占锁。这是针对 t1 的,它使 用页级锁模式。 , 行锁: o 查看地址为 11348b328 的行,其 rowid 为 0x102,表明这个锁是 行锁,在这里为独占锁。这是针对 t2 的,它使用行级锁模式。 , 数据库锁: o 查看地址为 10a3134d8 的行,表上有一个行锁。不过,tblsnum 0x100002 是一个数据库 tblspace,它是在服务器中保持数据库列 表的特殊表。因此,它行上的锁相当于锁定数据库。类型 S 表明 该锁是一个共享锁。 要在 onstat -k, 中找出 tblsnum 的表名,需要对 systables 表使用以下语 句: 清单 12. 识别 tbslnum 的表名 SELECT * FROM systables WHERE partnum=1049072; Output: tabname t2 owner informix partnum 1049072 tabid 101 rowsize 4 ncols 1 nindexes 0 nrows 0.00 created 07/20/2009 version 6619137 tabtype T locklevel R npused 0.00 fextsize 16 nextsize 16 flags 0 site dbname type_xid 0 am_id 0 pagesize 2048 ustlowts secpolicyid 0 protgranularity 回页首 在 sysmaster 数据库中使用 syslocks 表监控锁 您还可以通过在 sysmaster 数据库中使用 syslocks 表来监控锁。表 3 列出了 该表中的列并附带上说明: 表 3. syslock 表的字段 列 描述 dbsname 持有锁的数据库 tabname 持有锁的表的名称 rowidlk 持有锁的行的 ID(0 表明该锁是一个表锁) keynum 行的键号 Type 锁的类型 owner 锁持有者的会话 ID waiter 锁的第一个等待者的会话 ID 在 db1 中运行以下查询: 清单 13. db1 上的查询 CREATE DATABASE db1 WITH LOG; CREATE TABLE t3 (c1 int); CREATE INDEX idx1 ON t3(c1); INSERT INTO t3 VALUES(10); INSERT INTO t3 VALUES(11); INSERT INTO t3 VALUES(12); INSERT INTO t3 VALUES(13); BEGIN WORK; UPDATE t3 SET c1=99 WHERE c1=10; 从 syslocks 选择关于 db1 的信息: 清单 14. 从 syslocks 选择 db1 信息 SELECT * FROM syslocks WHERE dbsname='db1'; Output: dbsname db1 tabname t3 rowidlk 0 keynum 0 type IX owner 109 waiter dbsname db1 tabname idx1 rowidlk 0 keynum 1 type X owner 109 waiter dbsname db1 tabname t3 rowidlk 256 keynum 0 type X owner 109 waiter 输出结果明确显示这些锁是 db1 中的对象持有的。tabname 列列出了索引名。注意,rowidlk 的解释方式与 onstat -k 输出的 rowid 列一样。如果将 256 转换成十六进制得到 0x100,则表明该锁是一个页锁。 隔离级别 什么是隔离级别, “隔离级别是指您的程序与其他程序的并发操作的隔离程度” (“Informix Guide to SQL:教程”,IBM 2007 年)。每个隔离级别都提供不同的并发性级别和不同的数据一致性程度。 ANSI SQL-92 标准中提到了数据并发性的 3 个潜在问题(现象)。它们是: , 脏读:读取永远不可能存在的数据 下面是一个可能的脏读场景,其中 T1 和 T2 作为不同的事务: T1:开始一个事务 T1:修改一些数据 T2:读取修改的数据 T1:回滚事务 , 非重复读:读取修改后的数据或不能找到删除项 下面是一个可能的场景,其中 T1 和 T2 作为不同的事务: T1:读取一个数据项 T2:修改或删除该数据项 T1:再次读取该数据项 , 伪读:从第一次搜索中得到不同的结果 下面是一个可能的场景,其中 T1 和 T2 作为不同的事务: T1:基于某些条件搜索一组结果 T2:插入一组满足 T1 的条件的数据 T1:再次根据相同的条件搜索结果 IDS 提供 4 种隔离级别,它们为处理数据并发性问题提供一些机制: , 脏读隔离(读未提交) , 提交读隔离(读提交) , 游标稳定性隔离 , 可重复读隔离(可重复读和可系列化) 脏读隔离级别(读未提交) 脏读隔离不需要在读取的行上使用锁,因此不检查所需的行上是否有锁。使用该隔离级别的会话可能会得到脏数据,即该数据被另一个会话更新但尚未提交。 对于非日志数据库,这是唯一可以使用的隔离级别。 以上列出的所有 3 种现象都可以在这个隔离级别上出现。 提交读隔离级别(读提交) 提交读隔离仅允许会话读取已提交的行。它不在正在读取的行上放置锁,但检查该行是否放置了锁。因此这个隔离级别不会发生脏读。它是这样阻止脏读的: 清单 15. 阻止脏读 T1: CREATE TABLE t1 (c1 int) LOCK MODE ROW; T1: INSERT INTO t1 VALUES(1); T1: INSERT INTO t1 VALUES(2); T1: INSERT INTO t1 VALUES(3); T1: BEGIN WORK T1: UPDATE t1 SET c1=20 WHERE c1=2 (this places an exclusive lock on the row) T2: SET ISOLATION TO Committed Read T2: SELECT * FROM t1 WHERE c1=2 将拒绝 T2 读取该行,因为数据库服务器检测到该行已经放置了一个独占锁,表明它是一个未提交的行。 因为正在读取的行上没有放置任何锁,所以可能发生非重复读现象。例如: 清单 16. 非重复读现象 T1: BEGIN WORK T1: SET ISOLATION TO Committed Read T1: SELECT * FROM t1 WHERE c1=2 T2: BEGIN WORK T2: UPDATE t1 SET c1=20 WHERE c1=2 (places an Exclusive Lock on the row and updates it) T2: COMMIT; this releases the lock T1: SELECT * FROM t1 WHERE c1=2 (read the same row but this time it has different data) 另外,由于表没有锁定,所以并不能阻止发生伪读,因为另一个会话能够轻易插入其他行。 IDS 支持一种称为最新提交读 的提交读,它读取最新提交的行。因此,即使更改某个行并且未提交它,数据库服务器也能返回最新提交的行。最新提交读隔离阻止读取器在以上场景中收到锁错误,但仍然不能阻止类似于一般提交读隔离中出现的两种现象。 游标稳定性隔离级别 游标稳定性隔离在读取的行上放置一个共享锁,并且在锁定下一个行时释放该锁。 这个隔离级别能够阻止脏读和非重复读现象。下面显示了如何阻止脏读: 清单 17. 阻止脏读 T1: BEGIN WORK T1: UPDATE t1 SET c1=20 WHERE c1=2 (an exclusive lock is placed this row) T2: SET ISOLATION TO Cursor Stability T2: SELECT * FROM t1 WHERE c1=2 服务器拒绝 T2 读取该行,该行不能再放置一个共享锁,因为其上已经放置了一个独占锁(参见 表 1)。 清单 18 演示了游标稳定性如何阻止非重复读现象: 清单 18. 游标稳定性阻止非重复读现象 T1: SET ISOLATION TO Cursor Stability T1: declare a cursor for SELECT * FROM t1 WHERE c1=2 T1: open cursor and fetch the row T2: UPDATE t1 SET c1=20 WHERE c1=2 (Fail to put an exclusive lock on the row because a shared lock is already on it; see Table 1.) T1: SELECT * FROM t1 WHERE c1=2 注意,为了在读取的记录上放置一个锁,会话将需要使用一个游标来获取该记录。否则,将不能放置任何锁,就像在提交读隔离级别中一样。 使用这个隔离级别的会话可能出现伪读现象,就像在提交读隔离级别中一样。 可重复读隔离级别 在 IDS 中实现的可重复读隔离级别相当于 ANSI SQL 92 中的可重复读和可系列化。 这个隔离级别除了能够阻止脏读和非重复读现象之外,它还能阻止伪读现象。 如果数据库服务器需要为使用可重复读隔离的会话对表执行序列读,它将在该表上放置一个共享锁。不过,如果使用了索引扫描的话,共享锁仅能锁定与受影响的行相关的索引键。 查看以下例子。创建一个表并插入下面的值: 清单 19. 创建表并插入值 CREATE TABLE t1 (C1 INT) LOCK MODE ROW; INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); INSERT INTO t1 VALUES(4); INSERT INTO t1 VALUES(5); INSERT INTO t1 VALUES(6); INSERT INTO t1 VALUES(7); INSERT INTO t1 VALUES(8); INSERT INTO t1 VALUES(9); INSERT INTO t1 VALUES(10); 然后,事务 T1 对表执行以下命令: 清单 20. 执行事务 T1 T1: BEGIN WORK; T1: SET ISOLATION TO REPEATABLE READ; T1: SELECT * FROM t1 WHERE c1=5; onstat -k 输出显示在表 t1 上放置了一个共享锁,尽管请求的行仅为 c1=5: 清单 21. onstat -k 的输出 Locks address wtlist owner lklist type tblsnum rowid key#/bsiz 10a3134d8 0 111535cd8 0 HDR+S 100002 204 0 10a313558 0 111536d78 0 HDR+S 100002 202 0 10a313758 0 111536d78 10a313558 HDR+S 100243 0 0 10a44bcd8 0 111535488 0 S 100002 204 0 10a44bf58 0 111536528 0 S 100002 204 0 0x100243 的十进制值为 1049155。 运行以下 SQL 语句: select tabname from systables where partnum=1049155 返回的结果为: tabname t1 在这里,第二个事务 T2 继续执行以下 SQL 语句: T2: INSERT INTO t1 VALUES(20); T2 将收到错误 271(不能插入行)和 113(表被锁定)。 如果改为在 T2 上运行以下语句: T2: UPDATE t1 SET c1=20 WHERE c1=10 将返回一个表示不能获取需要更新的行的错误。如您所见,在表上放置共享锁对 并发性有巨大的影响。 如果您使用索引修改该例子: CREATE INDEX idx1 ON t1(c1); 重新开始执行: 清单 22. 重新开始执行 T1: BEGIN WORK; T1: SET ISOLATION TO REPEATABLE READ T1: SELECT * FROM t1 WHERE c1=5; onstat -k 的输出将类似于: 清单 23. onstat -k 的输出 Locks address wtlist owner lklist type tblsnum rowid key#/bsiz 10a3134d8 0 111535cd8 0 HDR+S 100002 204 0 10a313558 0 111536d78 0 HDR+S 100002 202 0 10a313658 0 111536d78 10a313d58 HDR+SR 100245 106 K- 1 10a313758 0 111536d78 10a313558 HDR+IS 1001ca 0 0 10a313b58 0 111536d78 10a313758 HDR+IS 100243 0 0 10a313d58 0 111536d78 10a313b58 HDR+SR 100245 105 K- 1 10a44bcd8 0 111535488 0 S 100002 204 0 10a44bf58 0 111536528 0 S 100002 204 0 这次,数据库服务器并没有在表 t1 上放置一个共享锁,而是在表上放置一个意 向共享锁。相反,共享锁被放置在相关的索引键上(查看 清单 23 的最后一列 的 “K -1” 值)。 如果 T2 尝试执行更新,如以上例子所示: T2: BEGIN WORK; T2: UPDATE t2 SET c1=5 WHERE c1=1 这次更新将成功。 从这个例子可以看到,索引能够改善并发性。 不过,如果 T2 尝试执行以下任意 SQL 语句时,会话将收到一个 “键值被锁定” 错误: INSERT INTO t1 VALUES(5); UPDATE t1 SET c1=20 WHERE c1=5; DELETE t1 SET c1=20 WHERE c1=5; 因为不能插入或更改 c1 等于 5 的行,这不仅避免了伪读现象,还增加了并发 性。 回页首 默认隔离和更改默认隔离 遵从 ANSI 的数据库的默认隔离级别是可重复读。不遵从 ANSI 的非日志数据库的默认隔离级别是脏读,不遵从 ANSI 的日志数据库的默认隔离级别是提交读。 要更改隔离级别,需要使用以下 SQL 语句: SET ISOLATION TO 其中 可以是以下之一: , DIRTY READ , COMMITTED READ , CURSOR STABILITY , REPEATABLE READ 在 SET ISOLATION 运行之后运行的 SQL 语句将拥有新的隔离级别。 回页首 监控隔离级别 可以使用 onstat -g sql 或 onstat -g ses 命令监控隔离级别。 例如,会话 ID 为 26 的会话(onstat -u 输出的第三列)显示以下信息: 清单 24. onstat -g ses 26 $ onstat -g ses 26 IBM Informix Dynamic Server Version 11.50.FC3 -- On-Line -- Up 00:36:15 -- 522240 Kbytes session effective #RSAM total used dynamic id user user tty pid hostname threads memory memory explain 26 informix - 128 16699 acme 1 196608 114440 off tid name rstcb flags curstk status 40 sqlexec 111972cf0 Y-BP--- 7839 cond wait netnorm - Memory pools count 2 name class addr totalsize freesize #allocfrag #freefrag 26 V 112bdc040 192512 81360 259 62 26*O0 V 112dcf040 4096 808 1 1 name free used name free used overhead 0 6576 scb 0 144 opentable 0 4360 filetable 0 1480 ru 0 600 log 0 16536 temprec 0 21664 keys 0 856 gentcb 0 1632 ostcb 0 2872 sqscb 0 38648 sql 0 72 rdahead 0 1120 hashfiletab 0 552 osenv 0 2680 sqtcb 0 3808 fragman 0 352 udr 0 10488 sqscb info scb sqscb optofc pdqpriority sqlstats optcompind directives 1125dc318 112c61028 0 0 0 2 1 Sess SQL Current Iso Lock SQL ISAM F.E. Id Stmt type Database Lvl Mode ERR ERR Vers Explain 26 - db1 CR Not Wait 0 0 9.24 Off Last parsed SQL statement : update t2 set c1=5 清单 25. onstat -g sql 26 $ onstat -g sql 26 IBM Informix Dynamic Server Version 11.50.FC3 -- On-Line -- Up 00:36:40 -- 522240 Kbytes Sess SQL Current Iso Lock SQL ISAM F.E. Id Stmt type Database Lvl Mode ERR ERR Vers Explain 26 - db1 CR Not Wait 0 0 9.24 Off Last parsed SQL statement : update t2 set c1=5 “CR” 表示提交读。脏读、游标稳定性、可重复读分别用 DR、CS 和 RR 表示。如果您使用最新提交读隔离级别,那么其表示符号为 LC。 结束语 现在,您已经很好地理解 IDS 使用哪些类型的锁来在多用户环境中维护数据的完整性。另外,您还学习了不同隔离级别如何影响并发性,以及如何避开这些隔离级别的潜参考资料 学习 , 您可以参阅本文在 developerWorks 全球站点上的 英文原文。 , “IBM Informix Guide to SQL: Tutorial“(IBM,2007 年):了解 SQL 的 Informix 实现,包括 SQL 语句、数据类型和提供数据库结构信息的 系统目录表。 , developerWorks Informix 专区:获取扩展您的 Informix 技能所需的资 源。 , “IDS Detective Game”(developerWorks,2008 年 4 月):通过一个 称为 “IDS Detective Game” 的互动游戏学习或教授 Informix Dynamic Server(IDS)和关系数据库的基础知识。 , IDS roadmap for administrators, developers, and end users:查找 关于 IDS 的各个方面的资源,包括、安装、配置、管理、调优和监 控等。 , Informix Education Training Path:查看要掌握特定技能或通过特定认 证所需的课程。 , Informix 库:从在线手册或 IDS Information Center 更多地了解关于 IDS 的详细信息。 , IBM Informix Dynamic Server 11.50 Information Center:查找使用 IDS 系列产品和特性所需的信息。 , developerWorks Information Management 专区:在这里可以学到更多关 于 Information Management 的知识。还可以找到技术文档、how-to 文 章、、下载、产品信息等。 , 随时关注 developerWorks 技术活动和网络广播。 获得产品和技术 , 试用版:Informix Dynamic Server Express Edition V11.50:下载 Informix Dynamic Server Express Edition 试用版本开始使用 IDS。 , Informix Dynamic Server Enterprise and Developer Edition:下载 Informix Dynamic Server Enterprise or Developer Edition 免费试用 版本。 , 下载 IBM 产品评估试用版软件 或 IBM SOA Sandbox for Reuse,并开始 使用来自 DB2?、Lotus?、Rational?、Tivoli? 和 WebSphere? 的应用程 序开发工具和中间件产品。 讨论 , 参与论坛讨论。 , IDS 专家博客:阅读世界各地的开发和技术支持工程师关于 Informix Dynamic Server 的技术说明。 , 参与 developerWorks blogs 并加入 My developerWorks 社区;您可以 通过个人信息和定制主页获得符合自己的兴趣的 developerWorks 文章, 并与其他 developerWorks 用户进行交流。 在问题。
/
本文档为【南京二氧化锆烤瓷牙.doc】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索