数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。 加锁是实现数据库并发控制的一个非常重要的技术。当事务在对某个数据对象进行操作前,先向系统发出请求,对其加锁。加锁后事务就对该数据对象有了一定的控制,在该事务释放锁之前,其他的事务不能对此数据对象进行更新操作。 在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(Share Locks,即S锁)。当数据对象被加上排它锁时,其他的事务不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。 Oracle数据库的锁类型 根据保护的对象不同,Oracle数据库锁可以分为以下几大类:DML锁(data locks,数据锁),用于保护数据的完整性;DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(internal locks and latches),保护 数据库的内部结构。 DML锁的目的在于保证并发情况下的数据完整性,。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。 当Oracle 执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X 等多种模式,在数据库中用0-6来表示。不同的SQL操作产生不同类型的TM锁。 在数据行上只有X锁(排他锁)。在 Oracle数据库中,当一个事务首次发起一个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行 DML语句时,第一个会话在该条记录上加锁,其他的会话处于等待状态。当第一个会话提交后,TX锁被释放,其他会话才可以加锁。 当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致死锁的发生,产生ORA-60的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。 悲观封锁和乐观封锁 
一、悲观封锁 
锁在用户修改之前就发挥作用: 
Select ..for update(nowait) 
Select * from tab1 for update 
用户发出这条命令之后,oracle将会对返回集中的数据建立行级封锁,以防止其他用户的修改。 
如果此时其他用户对上面返回结果集的数据进行dml或ddl操作都会返回一个错误信息或发生阻塞。 
1:对返回结果集进行update或delete操作会发生阻塞。 
2:对该表进行ddl操作将会报:Ora-00054:resource busy and acquire with nowait specified. 原因分析 
此时Oracle已经对返回的结果集上加了排它的行级锁,所有其他对这些数据进行的修改或删除操作都必须等待这个锁的释放,产生的外在现象就是其他的操作将发生阻塞,这个这个操作commit或rollback. 
同样这个查询的事务将会对该表加表级锁,不允许对该表的任何ddl操作,否则将会报出ora-00054错误::resource busy and acquire with nowait specified. 二、乐观封锁 
乐观的认为数据在select出来到update进取并提交的这段时间数据不会被更改。这里面有一种潜在的危险就是由于被选出的结果集并没有被锁定,是存在一种可能被其他用户更改的可能。因此Oracle仍然建议是用悲观封锁,因为这样会更安全。 
阻塞 定义: 
当一个会话保持另一个会话正在请求的资源上的锁定时,就会发生阻塞。被阻塞的会话将一直挂起,直到持有锁的会话放弃锁定的资源为止。4个常见的dml语句会产生阻塞 
INSERT 
UPDATE 
DELETE 
SELECT…FOR UPDATE 
INSERT Insert发生阻塞的唯一情况就是用户拥有一个建有主键约束的表。当2个的会话同时试图向表中插入相同的数据时,其中的一个会话将被阻塞,直到另外一个会话提交或会滚。一个会话提交时,另一个会话将收到主键重复的错误。回滚时,被阻塞的会话将继续执行。 UPDATE 和DELETE当执行Update和delete操作的数据行已经被另外的会话锁定时,将会发生阻塞,直到另一个会话提交或会滚。 Select …for update 当一个用户发出select..for update的错作准备对返回的结果集进行修改时,如果结果集已经被另一个会话锁定,就是发生阻塞。需要等另一个会话结束之后才可继续执行。可以通过发出 select… for update nowait的语句来避免发生阻塞,如果资源已经被另一个会话锁定,则会返回以下错误:Ora-00054:resource busy and acquire with nowait specified. 死锁-deadlock 定义:当两个用户希望持有对方的资源时就会发生死锁. 
即两个用户互相等待对方释放资源时,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚. 
例子: 
1:用户1对A表进行Update,没有提交。 
2:用户2对B表进行Update,没有提交。 
此时双反不存在资源共享的问题。 
3:如果用户2此时对A表作update,则会发生阻塞,需要等到用户一的事物结束。 
4:如果此时用户1又对B表作update,则产生死锁。此时Oracle会选择其中一个用户进行会滚,使另一个用户继续执行操作。 
起因: 
Oracle的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。 DML锁分类表
表1 Oracle的TM锁类型 
锁模式 锁描述 解释 SQL操作 
0 none   
1 NULL 空 Select 
2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for update、Lock for update、Lock row share
 
3 SX(Row-X) 行级排它锁,在提交前不允许做DML操作 Insert、Update、Delete、Lock row share
 
4 S(Share) 共享锁 Create index、Lock share 
5 SSX(S/Row-X) 共享行级排它锁 Lock share row exclusive 
6 X(Exclusive) 排它锁 Alter table、Drop able、Drop index、Truncate table 、Lock exclusive
 
设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据的一致性和准确性。Oracle数据库封锁方式有三种:共享封锁,独占封锁,共享更新封锁 
  封锁类型
   Oracle RDBMS的封锁类型可分为如下三类:    1、内部级封锁 
   内部级封锁是用于保护ORACLE内部结构,由系统内部实现,用户不能访问,因此我们不必对此做过多的了解。    2、DDL级封锁(字典/语法分析封锁) 
   DDL级封锁也是由ORACLE RDBMS来控制,它用于保护数据字典和数据定义改变时的一致性和完整性。它是系统在对SQL定义语句作语法分析时自动地加锁,无需用户干予。字典/语法分析封锁共分三类: 
   (1)、字典操作锁:用于对字典操作时,锁住数据字典,此封锁是独占的,从而保护任何一个时刻仅能对一个字典操作。 
   (2)、字典定义锁:用于防止在进行字典操作时又进行语法分析,这样可以避免在查询字典的同时改动某个表的结构。 
   (3)、表定义锁:用于 一个SQL语句正当访问某个表时,防止字典中与该表有关的项目被修改。    3、DML级封锁 
   DML级封锁用于控制并发事务中的数据操纵,保证数据的一致性和完整性,其封锁对象可以是表或行。 
   对用户的数据操纵,Oracle可以自动为操纵的数据进行封锁,但如果有操纵授权,则为满足并发操纵的需要另外实施封锁。DML封锁可由一个用户进程以显式的方式加锁,也可通过某些   SQL语句隐含方式实现。 
   DML锁有如下三种封锁方式: 
   (1)、共享封锁方式(SHARE) 
   (2)、独占封锁方式(EXCLUSIVE) 
   (3)、共享更新封锁(SHARE UPDATE)    其中SHARE,EXCLUSIVE用于表封锁,SHARE UPDATE用于行封锁。 
   1、共享方式的表封锁 
   共享方式的表封锁是对表中的所有数据进行封锁,该锁用于保护查询数据的一致性,防止其它用户对已封锁的表进行更更新。其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的封锁,共享更新锁可以再施加,但不允许持有共享更新封锁的进程做更新。共享该表的所有用户只能查询表中的数据,但不能更新。共享方式的表封锁只能由用户用SQL语句来设置,基语句格式如下: 
    
   执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT,若该封锁暂时不能施加成功,则返回并由用户决定是进行等待,还是先去执行别的语句。 
持有共享锁的事务,在出现如下之一的条件时,便释放其共享锁: 
   A、执行COMMIT或ROLLBACK语句。 
   B、退出数据库(LOG OFF)。 
   C、程序停止运行。 
   共享方式表封锁常用于一致性查询过程,即在查询数据期间表中的数据不发生改变。    2、独占方式表封锁 
   独占方式表封锁是用于封锁表中的所有数据,拥有该独占方式表封锁的用户,即可以查询该表,又可以更新该表,其它的用户不能再对该表施加任何封锁(包括共享、独占或共享更新封锁)。其它用户虽然不能更新该表,但可以查询该表。 
   独占方式的表封锁可通过如下的SQL语句来显示地获得: 
   LOCK TABLE <表名>[,<表名>].... 
   IN EXCLUSIVE MODE [NOWAIT] 
   独占方式的表封锁也可以在用户执行DML语句INSERT、UPDATE、DELETE时隐含获得。 
   拥有独占方式表封锁的事务,在出现如下条件之一时,便释放该封锁: 
   (1)、执行COMMIT或ROLLBACK语句。 
   (2)、退出数据库(LOG OFF) 
   (3)、程序停止运行。 
   独占方式封锁通常用于更新数据,当某个更新事务涉及多个表时,可减少发生死锁。    DML锁有如下三种封锁方式: 
   (1)、共享封锁方式(SHARE) 
   (2)、独占封锁方式(EXCLUSIVE) 
   (3)、共享更新封锁(SHARE UPDATE) 
   其中SHARE,EXCLUSIVE用于表封锁,SHARE UPDATE用于行封锁。    1、共享方式的表封锁 
   共享方式的表封锁是对表中的所有数据进行封锁,该锁用于保护查询数据的一致性,防止其它用户对已封锁的表进行更更新。其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的封锁,共享更新锁可以再施加,但不允许持有共享更新封锁的进程做更新。共享该表的所有用户只能查询表中的数据,但不能更新。共享方式的表封锁只能由用户用SQL语句来设置,基语句格式如下: 
    
   执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT,若该封锁暂时不能施加成功,则返回并由用户决定是进行等待,还是先去执行别的语句。 
持有共享锁的事务,在出现如下之一的条件时,便释放其共享锁: 
   A、执行COMMIT或ROLLBACK语句。 
   B、退出数据库(LOG OFF)。 
   C、程序停止运行。 
   共享方式表封锁常用于一致性查询过程,即在查询数据期间表中的数据不发生改变。    2、独占方式表封锁 
   独占方式表封锁是用于封锁表中的所有数据,拥有该独占方式表封锁的用户,即可以查询该表,又可以更新该表,其它的用户不能再对该表施加任何封锁(包括共享、独占或共享更新封锁)。其它用户虽然不能更新该表,但可以查询该表。 
   独占方式的表封锁可通过如下的SQL语句来显示地获得: 
   LOCK TABLE <表名>[,<表名>].... 
   IN EXCLUSIVE MODE [NOWAIT] 
   独占方式的表封锁也可以在用户执行DML语句INSERT、UPDATE、DELETE时隐含获得。 
   拥有独占方式表封锁的事务,在出现如下条件之一时,便释放该封锁: <BR>(1)、执行   COMMIT或ROLLBACK语句。 
   (2)、退出数据库(LOG OFF) 
   (3)、程序停止运行。 
   独占方式封锁通常用于更新数据,当某个更新事务涉及多个表时,可减少发生死锁。    3、共享更新封锁方式 
   共享更新封锁是对一个表的一行或多行进行封锁,因而也称作行级封锁。表级封锁虽然保证了数据的一致性,但却减弱了操作数据的并行性。行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。 
   可通过如下的两种方式来获得行级封锁: 
   (1)、执行如下的SQL封锁语句,以显示的方式获得: 
   LOCK TABLE <表名>[,<表名>].... 
   IN SHARE UPDATE MODE [NOWAIT] 
   (2)、用如下的SELECT ...FOR UPDATE语句获得: 
   SELECT <列名>[,<列名>]... 
   FROM <表名> 
   WHERE <条件> 
   FOR UPDATE OF <列名>[,<列名>].....[NOWAIT] 
   一旦用户对某个行施加了行级封锁,则该用户可以查询也可以更新被封锁的数据行,其它用户只能查询但不能更新被封锁的数据行.如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式封锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。 
   当出现如下之一的条件,便释放共享更新锁: 
   (1)、执行提交(COMMIT)语句; 
   (2)、退出数据库(LOG OFF) 
   (3)、程序停止运行。 
   执行ROLLBACK操作不能释放行锁。 
   从上面讲述可见,ORACLE RDBMS的加锁机制,解决了并发事务的相容与互斥问题。相容保证事务的并发性,互斥确保数据的一致性。不同用户锁的相容与互斥关系由下图给出。    其中最后一行最后一列为其它用户提供在不同行上设置SHARE UPDATE锁。但当用户1在某行上进行更新操作时,用户2只有等待用户1提交事务后,才能更新自己所封锁的行。    中最后一行最后一列为其它用户提供在不同行上设置SHARE UPDATE锁。但当用户1在某行上进行更新操作时,用户2只有等待用户1提交事务后,才能更新自己所封锁的行。 
死锁    封锁虽然能够有效的解决并发操作,但是任何资源的独占都会有死锁的危险。例如:有两个事务T1,T2,T1对数据A施加独占封锁,T2对数据B施加了独占封锁。再假设T1要对数据B加锁,由于B已被T2独占封锁,因此T1置于等待状态,等待B被释放;现在若T2也要对A进行封锁,由于A已被T1独占封锁,因此T2也被置于等待状态。这样就形成了两个事务相互等待的状态,而且永远不能结束,此种情况称为死锁。 
   在Oracle系统中能自动发现死锁,并选择代价最小的,即完成工作量最少的事务予以撤消,释放该事务所拥有的全部锁,记其它的事务继续工作下去。 
   从系统性能上考虑,应该尽可能减少资源竞争,增大吞吐量,因此用户在给并发操作加锁时,应注意以下几点: 
   1、对于UPDATE和DELETE操作,应只封锁要做改动的行,在完成修改后立即提交。 
   2、当多个事务正利用共享更新的方式进行更新,则不要使用共享封锁,而应采用共享更新封锁,这样其它用户就能使用行级锁,以增加并行性。 
   3、尽可能将对一个表的操作的并发事务施加共享更新锁,从而可提高并行性。 
   4、在应用负荷较高的期间,不宜对基础数据结构(表、索引、簇和视图)进行修改

解决方案 »

  1.   

    ORCLE回滚表空间总结
    回滚表空间也成为undo表空间,undo表空间时用来存储数据库生成的undo信息,一旦你执行的事务或语句由于某种原因失败了,或者如果你用一条rollback语句请求回滚,这是就可以利用这些undo信息将数据放回到修改前的样子。也就是说,undo表空间具有取消一条语句或一组语句的作用。例如,假设我们的事务执行了一个insert语句,这条语句导致分配一个新区段。通过执行这个insert,我们将得到一个新的块,格式化这个块后在其中放上一些数据。此时,可能出现另外某个事务,它也向这个块中插入数据。如果要回滚我们的事务,显然不能取消对这个块的格式化和空间分配。因此,Oracle回滚时,它实际上会做与先前逻辑上相反的工作。对于每个insert,Oracle会完成一个Delete。对于每个delete,Oracle会执行一个insert。对于每一个update,Oracle则会执行一个“反update”,或者执行另一个update将修改前的行放回去。
    什么操作会生成最多和最少的undo信息?
    如何释放undo表空间?
    分析常见的ORA-01555:snapshot too old 错误。
    稳测试中验证:当undo表空间用完时,数据库是否能够正常提供服务。
      

  2.   

    进行DRS长稳性能测试,undo表空间仍然增长过快,通过找资料,上网查资料,了解到undo表空间增长的原因时由于长事务造成的,这是因为代码中的批量删除数据造成的,由于undo表空间的磁盘空间没有及时的释放,所以推测可能因为代码中的事务句柄泄露造成事务没有commit或roolback,但是通过查看数据库系统中的事务信息,并没有未释放的事务,基于表空间是循环使用存储空间的,所以减小undo表空间的大小,在以后几天的长稳测试中验证:当undo表空间用完时,数据库是否能够正常提供服务。
      

  3.   

    1、 undo表空间的数据是非常非常重要的,只有commit,rollback才会被释放掉.是不可以用手动清除的。   
    2、 undo表空间主要是存储没有commit或rollback的delete和update的sql语句;缩小程序代码中相关的事务,及时的提交或回滚可以减少undo表空间的消耗; 
    3、释放表空间的方法就是删除回滚表空间后再重新创建,对应的sql语句如下:
            alter system set undo_tablespace = ‘’;
            drop tablespace undotbs including contents and datafiles cascade constraints;
             create undo tablespace undotbs datafile ‘/home/oracle/oradata/dmc/undotbs.dbf’ size 3000m;
            alter system set undo_tablespace =‘undotbs’;
    查看数据库系统的事务执行情况的sql语句为:
              select * from V$transaction;
      

  4.   

    第一迭代敏捷测试总结
        截止到10月10日,中间件C05版本的第一个迭代敏捷测试结束,整个测试过程都是可控的,而且尽量使开发与测试相辅相成、有条不紊的进行,但是在该迭代的测试过程中仍然暴露出来一些管理上的不足,现总结如下:
    一、 开发归档规范化问题。
        开发归档规范化问题在整个敏捷测试的环境中非常的重要,如果管理上稍有疏忽,都会大大降低测试人员的工作效率,就像在这个迭代中转测试的第一天,就因为归档版本时多次出错,导致所有测试人员一天都不能投入到测试的进度中。
    开发归档规范化问题主要体现在以下四个方面:
    1、 开发人员开发完成的代码没有及时的归档。也就是说,开发人员已经完成了某个   story的实现,由于没有及时的归档,即使我们更新了当前的环境,仍然不能进行相应的测试。在这样的情况下,测试人员是不接收任何的补丁的,所以只有等待开发人员归档后再次更新环境,这样的流程走下来,就会使测试人员的效率降低一半。
    建议:开发组每天归一次版本,请每天下班前把实现的功能及时归档;测试组每天只更新一次环境,并且不接受个人给予的任何补丁(这点请开发人员和测试人员都需要注意的地方)。
      

  5.   

    2、 未完成的代码进行归档导致一些未知的错误。在转测试的第一天,这个问题就出现过,当时导致的问题是epg启动不起来,并报“某个类找不到”的错误,遇到这样的问题,我们需要找开发人员进行定位,而且还需要开发组重新归档,测试组重新更新环境,这个过程则阻塞了整个测试组的测试。
             建议:希望每一个开发人员都能够意识到这个问题的严重性,提高大家的工作效率应该是每个人的责任。“开发组每天归一次版本,测试组每天只更新一次版本”的措施也是为了约束大家更好的管理代码的方法。
    3、 代码关联和代码覆盖问题。也就是说,某个功能新增的代码或修改原有代码的时候造成其他功能模块的测试阻塞,同样很大程度的影响测试人员的工作进度。而且需要开发人员来定位,有时候某个问题的定位需要花费大量的时间。换个角度思考,如果这种情况通过测试的方式能够及时的暴露出来,那是幸运的,如果引出的问题是概率性出现的,这种情况下就有可能造成不可估计的风险。
    建议:需要开发人员之间要有很好的沟通,开发人员在修改某段代码时,一定要向调用这段代码的相关人员进行沟通,力求做到修改后的代码不会影响原有的功能。同时,也希望在这种情况下,开发人员能够在story转测试的时候向测试人员提供一个继承性分析报告,所谓的继承性分析报告,就是开发人员在实现某个功能时,可能会对哪些功能模块造成影响,以及自己实现的某个功能哪个部分需要加大测试粒度,毕竟测试人员只是进行的黑盒测试,不了解该功能代码的实现逻辑,开发人员提供一些好的测试方法和测试建议是非常重要的。
      

  6.   

    二、 问题单流程问题。
    部分开发人员走问题单的流程是不合理的。按照规定,问题单的流程应该是:发现问题—确认问题—提问题单—开发人员修改—修改后的代码进行归档—测试更新归档后的版本—开发人员将问题单走到提单人—提单人回归问题单—关闭问题单。但是,在这轮的迭代中,有很多问题单走到了提单人处,但是提单人回归该问题单时仍然不通过,找相关开发定位,发现是修改后的代码没有归入新的版本中,所以希望开发人员务必按照问题单的流程来走,这样既可以提高测试人员的工作效率,也可以节省开发人员的时间。
    建议:每次开发组归档时都标一个归档版本号,例如:build1、build2、build3、……,在开发人员将问题单走到提单人处时,希望开发人员在问题单里说明一下:该问题单修改后的代码归入到哪个归档版本里,也就是标明该问题单的归档版本号。
      

  7.   

    组播中继
    在IPTV的应该知道还有这个方式~~~
    其实通俗的讲:单播+组播=组播中继。
    用业务来讲就是:在组播中继的方式下,边缘节点媒体服务器获取上级节点单播流后,发送组播流到接入网设备,如BAS或DSLAM,由BAS或DSLAM复制组播流到终端。组播中继组网情况下,无论有无终端点播直播频道,媒体服务器均发送组播流到承载网设备。