锁(lock)用于管理对共享资源的并发访问。
在必要时才提交,不要提前。
锁的问题:
1.丢失更新
session1 | session2 |
(1)查询一行数据 | (2)查询同一行数据 |
(3)update该行并提交 | |
(4)update该行并提交 | |
这个过程被称为丢失更新 | 因为(3)所做的所有修改都会丢失 |
2.锁定策略:悲观锁(pessimistic)乐观锁(optimistic)
悲观锁 这种方式在用户修改数值之前就开始生效了 |
乐观锁 所有锁定动作都延迟到即将执行更新之前才进行 实现方法:使用版本列的乐观锁,使用用户总和校验的乐观锁 |
3.阻塞
阻塞的Insert 带主键或唯一约束 引用完整性约束 |
阻塞的Merger、update和delete |
4.死锁
5.锁升级
锁的类型
DML锁 select、insert、update、merge、delete 可能是行级锁也可能是表级锁 1.TX锁 事务发起第一个修改时会得到TX锁 Oracle没有使用锁管理器,Oracle锁定过程如下: (1)找到想锁定的那一行地址 (2)到达那一行 (3)就地锁住这一行,就在行的位置上(如果这一行已经被锁住,就等待锁住他的事务结束,除非指定nowait) |
DDL锁 create和alter语句等,可以保护对象结构定义 |
内部锁和闩latch 保护内部数据结构 |
SQL> create table dept 2 as select * from scott.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. |