`
dingjob
  • 浏览: 180894 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

事务中的一些问题

阅读更多
近期遇到了不少并发和事务问题,总结如下

1.锁 必须在取数据之前。  现在的事务主要是通过锁数据并通过在后面的校验中验证状态实现的,
要注意,后面的验证数据一定要是加锁之后取出来的数据,比如验证订单状态能否进行当前操作时
要重新取一下订单。

2.锁的粒度

原则:粒度越小越好,但同时也要在不影响性能的情况下,考虑实现的方便和代码的结构性。
举例: 当仅仅时对订单进行操作时,不要锁住客户,但是由于下单时没有订单,这种情况下就要锁客户,续订和续订的修改是公用的方法,这样在这方法中就要判断什么时候要锁客户,什么时候要锁订单,导致多余的判断,代码结构不好。这个时候考虑所有订单操作都锁住客户表。

军哥原来提出过一个方法,就是专门提供一个表用来加锁,这中方法可以完全避免死锁的问题
不失为一种好的方法。

3.orcle 具有隐含锁,有些操作不需要加锁
ORACLE锁的类型在正常情况下,ORACLE会自动锁住需要加锁的资源以保护数据,这种锁是隐含的,叫隐含锁。下面指明了会产生隐含锁的SQL语句:
INSERT;UPDATE;DELETE;


4.同一个事务中可以加两次或两次以上的锁。

5.在事务外面加锁不起作用,加锁的forupdate 作为一条普通select 语句执行,下一个线程不会在锁的位置等待。

6.一些用于查询锁的sql,
应用场景,由于在测试并发时会经常用到一些锁表的问题。需要找出被什么人锁住,是在程序中锁住,还是在Pl/SQL
中锁住。

可以用如下的SQL 配合查询。
(1) 在BOSS 的查询,后面的是王英杰提供的查询。但是DMP的这几个系统表的权限没有开给我们。
select object_type,object_name,owner from dba_objects where object_id in (
select object_id  from v$locked_object);
select * from v$session where username in ('FBACKOFFICE') order by status;


(2) SELECT c.sid,
       c.serial#,
       c.terminal || '-' || c.osuser || '-' || MODULE || ' hold ' ||
       DO.object_type || ' ' || DO.object_name xx
  FROM v$lock a, v$lock b, v$session c, dba_objects DO
WHERE b.type = 'TX'
   AND a.sid = b.sid
   AND c.sid = a.sid
   AND DO.data_object_id = a.id1;

搜索结果如下:

1 202 22204 ALIBABA-11823-zhaobo.dingzhb-PL/SQL Developer hold TABLE CRM_CUSTOMER

分析下: lock 表 存当前所有的锁的情况,session 是当前访问数据库所有的用户session ,dba_objects   存放了所有表的信息,每个表作为一条记录,通过关联这三张表就可以搜索出所有的锁住表的记录

lock 的Type 有 TX TM 等  TX是记录锁,TM是表锁,由于锁表也是线锁表再锁记录,这样通过
限定b.type = 'TX'所有的锁都是能查找到的

至于搜索出的记录集比较容易看清楚:
c.terminal  终端机: 你的机器名
c.osuser :你的用户
DO.object_type :终端所用的工具,即你的PL/SQL或者程序。
DO.object_name :被锁的表名称



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics