锁和闩
锁(lock)用于管理对共享资源的并发访问。
在必要时才提交,不要提前。
锁的问题:
1.丢失更新
session1 | session2 |
(1)查询一行数据 | (2)查询同一行数据 |
(3)update该行并提交 | |
(4)update该行并提交 | |
这个过程被称为丢失更新 | 因为(3)所做的所有修改都会丢失 |
2.锁定策略:悲观锁(pessimistic)乐观锁(optimistic)
悲观锁 这种方式在用户修改数值之前就开始生效了 |
乐观锁 所有锁定动作都延迟到即将执行更新之前才进行 实现方法:使用版本列的乐观锁,使用用户总和校验的乐观锁 |
3.阻塞
阻塞的Insert 带主键或唯一约束 引用完整性约束 |
阻塞的Merger、update和delete |
4.死锁
5.锁升级
锁的类型
TX锁实验: SQL> create table dept Table created. SQL> create table emp Table created. Table altered. Table altered. SQL> alter table emp Table altered. SQL> create index emp_deptno_idx Index created. 启动一个事务: SQL> update dept 4 rows updated. |
查看: SELECT username, USERNAME SID RBS SLOT SEQ LMODE REQUEST SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction; XIDUSN XIDSLOT XIDSQN v$lock表的LMODE为6,REQUEST为0.查看Oracle Database Reference得到LMODE=6是一个排他锁。请求REQUEST=0则意味着你没有发出请求,也就是说你拥有这个锁。 这个v$lock表只有一行。Oracle不会在任何地方存储行级锁的列表。要查看某一行是否锁定,必须直接找到这一行。 RBS、SLOT和SEQ值与v$transaction匹配,这就是我的事务ID |
开启另外一个会话 SQL> update emp set ename=upper(ename); 14 rows updated. SQL> update dept set deptno=deptno-10; 现在这个会话被阻塞 |
回到原来会话 SELECT username, USERNAME SID RBS SLOT SEQ LMODE REQUEST SQL> select XIDUSN,XIDSLOT,XIDSQN from v$transaction; XIDUSN XIDSLOT XIDSQN SELECT (SELECT username BLOCKER SID 'ISBLOCKING' BLOCKEE SID SQL> commit; Commit complete. SELECT username, USERNAME SID RBS SLOT SEQ LMODE REQUEST 再另外一个会话也可以看到更新完成,结束了被阻塞状态。 SQL> update emp set ename=upper(ename); 14 rows updated. SQL> update dept set deptno=deptno-10; 4 rows updated. |
TM锁实验: oracle@test1: /home/oracle> sqlplus eoda/foo USERNAME SID ID1 ID2 LMODE REQUEST BLOCK TY
尽管每个事物只得到一个TX锁,但TM锁不同,修改了多少个对象,就能得到多少个TM锁。 |