ITPub博客

首页 > Linux操作系统 > Linux操作系统 > [IDS培训文档]第二章 并发控制

[IDS培训文档]第二章 并发控制

原创 Linux操作系统 作者:mrhutoo 时间:2013-09-06 07:59:15 0 删除 编辑
第二章 并发控制
并发是指多个用户在同一个时间操作相同数据。由于并发操作就带来了数据一致性得问题。IDS是通过锁(lock)技术来保证并发数据得一致性的。
1、锁的类型
1)共享锁(shared lock)
共享锁可以防止其他用户修改被锁住的目标,但多个用户对同一目标可以实施加共享锁。
2)排它锁(exclusive lock)
排它锁锁住的对象将谢绝所有其他用户的访问。
3)提升锁((promotable lock/update lock)
提升锁是用户在使用update游标时使用的锁。提升锁在数据修改之前是一个共享锁,当数据修改时,共享锁提升为一个排它锁。下面是一张锁冲突表:
A
---------------------------------------------------------------
S X U none
B S y n y y
X n n n y
U y n n y
-------------------
说明:S:共享锁 X:排它锁 U:提升锁
  A:持有锁的用户 B:申请锁的用户
  y:锁申请成功 n:锁申请失败
2、锁的粒度(granularity)
锁的粒度是指被加锁的对象的大小或范围。
锁的粒度越大,并发程度越低,锁资源开销越小;锁的粒度越小,并发程度越高,锁资源开销越大。
1)数据库级锁(database lock)
database dbname [exclusive/share];
默认情况下,IDS对数据库使用共享锁,如用户打开数据库:database dbname。
2)表级锁(table lock)
lock table tablename in exclusive/share mode;
当做如下操作时,IDS将自动对操作的表施加排它锁:
(1)alter index (2)alter table
(2)create index (3)drop index
(4)rename column (5)rename table
表级共享锁锁住的表将谢绝其他用户对该表数据的任何修改,但其他用户可以读该表的数据。表级排它锁锁住的表将谢绝其他用户的任何访问(除非使用“脏读”方式)。对于一个表的大量数据修改操作可以考虑使用表级排它锁。
3)页面锁(page lock)、记录锁(row lock)、键值锁(key lock)
页面锁锁住的对象是一个IDS数据页面,记录锁锁住的对象是一个记录。用户在创建表时可以选择对该表操作时使用页面锁或者记录锁。IDS建表时默认的锁方式是页面锁:
create table tablename
(

)lock mode page/row;
当IDS试图对该表的记录加锁时,它将根据长剑该表时定义的锁类型加锁。
键值锁是IDS用来锁住不存在的记录的方法,实际上是锁住该记录在表中的位置不被他用。例如:IDS在事务中删除一个表中的某一记录时,它将锁住该记录对应的键值,以免其他用户同时插入同一记录。
3、锁的生命周期
数据库级锁只有在关闭数据库时才能被释放。对于表级锁、记录锁、键值锁的生命周期依赖于所进行的数据库操作:selcet,update,delete等和数据库事务是否使用。如果数据库没有使用日志,那么只有当用户显示释放该锁时(unlock table tablename),IDS才释放表级锁。总之:当数据库事务结束时,它将释放所有在本事务中使用的锁;事务中对数据库数据修改时所加的所将保持到事务结束。
4、锁的隔离等级(isolation level)
隔离等级是指在并发环境下,一个应用隔离其他并发应用的等级。通过使用隔离等级,应用可以在读数据时指定使用锁资源的方式。使用隔离登机必须打开数据库日志。
1)set isolation to dirty read;
指定应用读数据时,对所读对象不施加任何锁。应用读数据时将不检查是否其他应用正在操作该数据。仅仅考虑系统开销,这种方式读数据是效率最高的。
2)set isolation to commited read;
指定应用读数据之前,首选对所读数据检查是否有其他应用正在修改该数据,以确保本应用读数据是已提交的数据。但这种方式在读数据时,并不对数据施加任何类型的锁,所以用户正在读的数据有可能其他用户正在修改。这种方式时IDS默认的读数据方式。
3)set isolation to cursor stability;
指定应用读数据时,如果使用“游标”,则对所读数据施加共享锁,该共享锁在读取下一记录时将被释放掉,也就是只对所读当前一条记录保持共享锁:如果不使用“游标”,该种读数据的方式与上一种相同。
4)set isolation to repeatable read;
指定应用读数据时,对所读数据全部施加共享锁,所有的锁资源在事务结束才被释放。使用这种方式,所有扫描过的数据全部施加共享锁,即使部分数据不满足读数据条件,但在扫描过程种扫描过。(如果全表扫描,则这种方式与使用表级锁效果是一样的)。
5、锁冲突模式
当应用由于锁资源引起冲突时,可以通过设置锁冲突来解决。
1)set lock mode to wait;
这种方式下,应用遭遇锁冲突时,将无限制等待下去直到申请到所需锁资源为止。
2)set lock mode to no wait;
这种方式下,应用遭遇锁冲突时,将立即返回应用:数据库操作错,如:107:Record is locaked.这种方式是IDS默认的冲突等待方式。
3)set lock mode to wait n;(n是应用设置的等待时间)
这种方式下,应用遭遇锁冲突时,将在时间n内反复申请所需锁资源直到申请成功或者设置时间n用完。在IDS处理OLTP(Online Transaction Processing)联机交易(如MCS中储蓄、会计、信用卡日间实时交易)时,应该在E/C程序首部,首先设置锁冲突等待时间,这样以来可以避免很多不必要的由于锁冲突引起的数据库操作失败。
6、死锁(deadlock)
假设用户A持有x锁,用户B持有y锁。此时,用户A申请y锁,同时用户B申请x锁。这样一来就会出现用户A、B同时等待对方释放自己的锁,于是出现“死锁”。对于“死锁”,IDS本身提供了一套检测、恢复机制来避免“死锁”的发生。
7、举例:
假设有两个用户同时在操作同一数据库workdb中的表test,表test的脚本:
$create table test
(
code char(3),
time char(20),
name char(20)
)lock mode page;
$create upique index m_idx on test(code);
先进行如下练习:
(1)用户A进行如下操作:
begin work;
update test set time=”2” where code=”sam”;
(2)用户B同时进行如下操作:
   select * from test where code=”abc”;
问题:上述操作结果如何?
用户B的select操作失败了。因为用户A操作时对表test施加了页面级的排他锁(这些锁将保留到事务结束),而用户B试图扫描被页级排它锁锁住的页面,所以操作失败。
(3)用户A进行如下操作:
   rollback work;
   alter table test lock mode(row);
   begin work;
   update manufact set time=”2” where code=”sam”;
说明:
本次操作成功。因为该操作通过索引读取记录,而记录未被步骤3的记录锁锁住。
(4)用户B进行如下操作:
select * from test where code=”hro”;
说明:
本次操作成功。因为该操作通过索引读取记录,而该记录未被步骤3的记录锁住。
(5)用户B进行如下操作:
select * from test;
说明:
本次操作失败。因为该操作试图顺序扫描表test,而步骤3对test施加了记录排它锁,而且本操作使用了”commited read”的读数据方式(系统默认)。
(6)用户B进行如下操作:
set isolation to dirty read;
select * from test;
说明:
本次操作成功。因为该操作设置了“脏读“方式,将忽略说有锁冲突。
(7)用户B进行如下操作:
set isolation to commited read;
set lock mode to wait;
select * from test;
说明:
本次操作处于等待方式。因为该操作设置了“commited read“和“锁冲突等待”方式,所以本操作被步骤3申请的锁阻塞,等待其释放锁资源。
(8)用户A进行如下操作:
commit work;
说明:
本次操作将释放步骤3申请的锁资源,步骤7操作成功。
(9)用户A进行如下操作:
set isolation to repeatable read;
begin work;
update test set time=”2” where  name=”Julio”;
说明:
本次name字段没有索引,所以本次操作将采取顺序扫描方式;另外,由于设置了”repeatable read”读模式,所以test表的所有记录都将被锁住。
(10)用户B进行如下操作:
set lock mode to no wait;
update test set time=”2” where code=”sam”;
说明:
本次操作失败。虽然本次操作通过索引定位记录,但是步骤9中用户A已经锁住(共享锁)test中表所有记录,而且用户B设置了”no wait”锁冲突方式,所以操作失败。
(11)用户B进行如下操作:
select * from test where code=”sam”;
说明:
本次操作成功。因为本次操作使用索引定位记录,而且使用”commited read”读方式对记录施加共享锁,与步骤9中申请的共享锁不冲突,所以操作成功。
 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24955184/viewspace-772252/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-11-20

  • 博文量
    27
  • 访问量
    67128