表的锁定

                               锁的概念
   锁出现在数据共享的场合,用来保证数据的一致性。当多个会话同时修改一个表时,需要对数据进行相应的锁定。
   锁有“只读锁”、“排它锁”,“共享排它锁”等多种类型,而且每种类型又有“行级锁”(一次锁住一条记录),“页级锁”(一次锁住一页,即数据库中存储记录的最小可分配单元),“表级锁”(锁住整个表)。
                                   排它锁和共享锁
   排它锁又称为写锁((Exclusive lock,简记为X锁)),若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务的末尾将资源上的原始锁释放为止。在更新操作(INSERT、UPDATE 或 DELETE)过程中始终应用排它锁。
     共享锁又称为读锁(Share lock,简记为S锁),若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。 
     共享锁:由非更新(读取)操作创建的锁。其他用户可以并发读取数据,但任何事务都不能获取数据上的排它锁,直到已释放所有共享锁。   
若为“行级排它锁”,则除被锁住的行外,该表中其他行均可被其他的用户进行修改(Update)或删除(delete)。若为“表级排它锁”,则所有其他用户只能对该表进行查询(select)操作,而无法对其中的任何记录进行修改或删除。当程序对所做的修改进行提交(commit)或回滚(rollback)后,锁住的资源便会得到释放,从而允许其他用户进行操作。 
    有时,由于程序的原因,锁住资源后长时间未对其工作进行提交;或是由于用户的原因,调出需要修改的数据后,未及时修改并提交,而是放置于一旁;或是由于客户服务器方式中客户端出现“死机”,而服务器端却并未检测到,从而造成锁定的资源未被及时释放,影响到其他用户的操作。 
   如果两个事务,分别锁定一部分数据,而都在等待对方释放锁才能完成事务操作,这种情况下就会发生死锁。
                             隐式锁和显式锁 
   在Oracle数据库中,修改数据操作时需要一个隐式的独占锁,以锁定修改的行,直到修改被提交或撤销为止。如果一个会话锁定了数据,那么第二个会话要想对数据进行修改,只能等到第一个会话对修改使用COMMIT命令进行提交或使用ROLLBACK命令进行回滚撤销后,才开始执行。因此应养成一个良好的习惯:执行修改操作后,要尽早地提交或撤销,以免影响其他会话对数据的修改。
【训练1】  对emp表的SCOTT雇员记录进行修改,测试隐式锁。 
    步骤1:启动第一个SQL*Plus,以SCOTT账户登录数据库(第一个会话),修改SCOTT记录,隐式加锁。 
    UPDATE emp SET sal=3500 where empno=7788; 
    执行结果: 
     已更新 1 行。 
     步骤2:启动第二个SQL*Plus,以SCOTT账户登录数据库(第二个会话),进行记录修改操作。 
     UPDATE emp SET sal=4000 where empno=7788; 
      执行结果,没有任何输出(处于等待解锁状态)。 


      步骤3:对第一个会话进行解锁操作: 
     COMMIT; 
步骤4:查看第二个会话,此时有输出结果: 
已更新 1 行。 
步骤5:提交第二个会话,防止长时间锁定。 
说明:两个会话对同一表的同一条记录进行修改。步骤1修改SCOTT工资为3500,没有提交或回滚之前,SCOTT记录处于加锁状态。步骤2的第二个会话对SCOTT进行修改处于等待状态。
步骤3解锁之后(即第一个会话对SCOTT的修改已经完成),第二个会话挂起的修改此时可以执行。最后结果为第二个会话的修改结果,即SCOTT的工资修改为4000。读者可以使用查询语句检查。 
以上是隐式加锁,用户也可以使用如下两种方式主动锁定行或表,防止其他会话对数据的修改。表3-3是对行或表进行锁定的语句。
                  表的显式锁定操作语句 
select fror update   锁定表行,防止其他会话对行的修改 
lock table 锁定表,防止其它会话话对表的修改
  锁定行 
【训练1】  对emp表的部门10的雇员记录加显式锁,并测试。 
步骤1:对部门10加显式锁: 
SELECT empno,ename,job,sal FROM emp WHERE deptno=10 FOR UPDATE; 
结果为: 
     EMPNO ENAME   JOB              SAL 
------------------ -------------- ------------------ ------------------ 
     7782  CLARK    MANAGER        2450 
      7839  KING      PRESIDENT       5000 
      7934  MILLER    CLERK           1300 
步骤2:启动第二个SQL*Plus(第二个会话),以SCOTT账户登录数据库,对部门10的雇员CLARK进行修改操作。 
UPDATE emp SET sal=sal+100 where empno=7782; 
执行结果: 
没有任何输出(处于等待解锁状态)。 
步骤3:在第一个会话进行解锁操作: 
COMMIT; 
步骤4:查看第二个会话,有输出结果: 
已更新 1 行。 
说明:步骤1对选定的部门10的雇员加锁,之后其他会话不能对部门10的雇员数据进行修改或删除。如果此时要进行修改或删除,则会处于等待状态。使用COMMIT语句进行解锁之后,如果有挂起的修改或删除操作,则等待的操作此时可以执行。
 锁定表 
LOCK语句用于对整张表进行锁定。语法如下: 
LOCK TABLE 表名 IN {SHARE|EXCLUSIVE} MODE 
对表的锁定可以是共享(SHARE)或独占(EXCLUSIVE)模式。共享模式下,其他会话可以加共享锁,但不能加独占锁。在独占模式下,其他会话不能加共享或独占锁。 
【训练1】  对emp表添加独占锁。 
步骤1:对emp表加独占锁: 
LOCK TABLE emp IN EXCLUSIVE MODE; 
结果为: 
表已锁定。 
步骤2:对表进行解锁操作: 
COMMIT; 
说明:当使用LOCK语句显式锁定一张表时,死锁的概率就会增加。同样地,使用COMMIT或ROLLBACK命令可以释放锁。 
   注意:必须没有其他会话对该表的任何记录加锁,此操作才能成功

你可能感兴趣的:(oracle,sql,应用服务器,单元测试)