LOCK(1)-TX LOCK

本文深入解析Oracle数据库中的锁机制,包括TX锁、TM锁及DDL锁等类型,并通过实例展示了如何利用v$lock视图来查看锁持有者与请求者。

 

  1. Lock type(1)
    参考TOM - expert oracle database
    1. Overview
      1. TX locks: 一个数据修改的事务需要获得TX lock.
      2. TM lockDDL lock:这种锁用于保证数据对象的结构不被修改. TM是在修改对象的内容时获得,DDL是在修改对象的本身.
    1. Lock的分类
      1. DML
        1. select, update, insert, delete, merge时需要,主要包括TXTM. 允许数据并发更改, dml时锁住特殊行数据或者在表级别上锁住每个行.
      1. DDL:create, alter object时需要,主要用于保护数据的结构.
      2. Internal锁和latches
    1. DML:用于保证两件事(上面提到的两种锁),一个防止同时修改1,一个防止修改对象内容时对象本身被alter(drop).
      1. TX(Transaction) Locks:
        事务锁是在事务的第一个改变发生的时候获得,事务结束释放. 每个修改的行或者select for update的行都会指向那个事务关联的TX.
        这个代价看起来高其实不然.
        oracle
        中锁是数据的一部分,而传统的数据库锁的实现是基于内存的lock manager: 锁资源是有限的,每个锁住的行保存在一个长链表中.
        传统:获得要锁定的行地址-->放到lock manager中排队-->锁住list-->遍历该list中该行是否已被锁定-->没有则新建一entry in list来确认已锁住-->unlock list.
        commit,再次排队-->lock list-->遍历并且释放你的锁-->unlock list
        传统方式成本很高,
        oracle
        ,不需要lock manager建立额外的list object:
        找到要改的行的地址
        -->到该行-->锁住行

        具体内部的实现参见
        :
        http://www.360doc.com/content/061201/11/15284_279199.html
        记录的行头中包含lb标识,指向一个itl(事务槽),空则表示该记录没有被修改过.
        1)
        修改过之后,记录的lb标识(锁或者事务)指向一个itl,itllock标识为1 表示该事务锁定了一条记录,flag为空表示该事务没有提交(active session),提交后,其他不变(lb,lck),只有flag变为U(提交)
        2)
        一个session请求lock,同样去看lb,然后到itl,如果不是active,则去更新itl,lb. 如果是active,则等待,enqueue lock fixed array中建立等待对象(按照lock时间顺序排序).同时设置time-out时间(到了会自动醒来查查状态).
        3)Active会话commit,修改flag,并且检查enqueue队列,通知那个等待时间最久的会话激活.
        -
        此段类似与tom说的,tom更底层直接一些. Transaction ID的含义-回滚的...
         

select username,

v$lock.sid,

trunc(id1/power(2,16)) rbs,

bitand(id1,to_number('ffff','xxxx'))+0 slot,

id2 seq,

lmode,

request

from v$lock, v$session

where v$lock.type = 'TX'

 and v$lock.sid = v$session.sid

 and v$session.username = 'U1';
           USERNAME        SID        RBS        SLOT        SEQ        LMODE        REQUEST

1        U1                    154         9        24        429        6        0

 

v$transaction中验证一下:
 

select XIDUSN, XIDSLOT, XIDSQN

from v$transaction;

           XIDUSN        XIDSLOT        XIDSQN

1        9        24        429

 

session1

update t1 set salary=salary+100 where id=3;

 

session2

update t1 set salary=salary+100 where id=2;

 

session1中再运行session2row update,阻塞等待...

update t1 set salary=salary+100 where id=2;

 

查询锁

           USERNAME        SID        RBS        SLOT        SEQ        LMODE        REQUEST

1        U1        154        1        6        370        0        6

2        U1        139        1        6        370        6        0

3        U1        154        9        24        429        6        0

会话1拥有回滚段9-24-429(也就是事务ID),等待的是1-6-370(而该事务正在被139会话2使用)
 

查询事务

           XIDUSN        XIDSLOT        X  IDSQN

1        1        6        370

2        9        24        429

确认了一下只有两个active seesion..

 

sql查询requestorholder(v$lock中自查询)

select

(select username from v$session where sid=a.sid) blocker,

a.sid,

' is blocking ',

(select username from v$session where sid=b.sid) blockee,

b.sid

from v$lock a, v$lock b

where a.block = 1

and b.request > 0

 and a.id1 = b.id1

 and a.id2 = b.id2;

 

           BLOCKER        SID        'ISBLOCKING'        BLOCKEE        SID

1        U1        139         is blocking         U1        154

 

commit会话2

锁信息

           USERNAME        SID        RBS        SLOT        SEQ        LMODE        REQUEST

1        U1        154        9        24        429        6        0

 

而且,无论该事务中锁定了多少行记录,只需要该锁1(而不是1行一把),这是因为内部结构的实现-每个块中记录事务(包含事务是否activelock状态),而每行记录则指向该事务.

 

SQL> update t1 set salary=salary+200;

3 rows updated.

查询TX,仍然只有一条.
           USERNAME        SID        RBS        SLOT        SEQ        LMODE        REQUEST

1        U1                  149        2        46        495        6        0

 

另外参考:
 

oracle table-lock的5种模式

http://dennis-zane.javaeye.com/blog/57491
 

在数据库系统中,行锁竞争(Row-Level Lock Contention)是一个常见的性能瓶颈,尤其是在高并发环境中。当多个事务尝试同时修改同一数据行时,就会发生**Tx Row Lock Contention**,即事务行锁竞争问题。 行锁机制用于确保事务的隔离性和一致性,避免脏读、不可重复读和幻读等问题。然而,在并发写入频繁的情况下,这种机制可能引发显著的竞争问题,从而降低系统吞吐量并增加响应时间。 ### 行锁竞争的原因 1. **热点数据访问**:多个事务频繁访问并修改相同的数据行,例如库存更新、账户余额变更等场景。 2. **长事务持有锁**:长时间运行的事务会延迟其他事务对数据行的访问,导致队列积压。 3. **低效的事务设计**:未优化的SQL语句或业务逻辑可能导致不必要的锁持有时间延长。 4. **索引缺失或设计不良**:缺乏合适的索引会导致数据库进行全表扫描,进而引发更多行被锁定[^1]。 ### 常见影响 - **等待事件增加**:如`enq: TX - row lock contention`等事件频繁出现。 - **事务延迟上升**:用户感知到操作变慢,响应时间增加。 - **死锁风险提升**:多个事务互相等待对方释放锁资源,最终触发死锁检测机制回滚部分事务。 ### 缓解策略 1. **优化事务逻辑**: - 缩短事务执行时间,尽早提交事务以释放锁。 - 将大事务拆分为多个小事务,减少锁争用的可能性。 2. **调整隔离级别**: - 在允许的前提下使用较低的隔离级别(如`READ COMMITTED`),减少锁的粒度和持续时间。 3. **改进SQL与索引设计**: - 确保查询使用正确的索引,减少不必要的行锁定。 - 避免全表扫描,尤其是在更新操作中。 4. **使用乐观锁机制**: - 在应用层实现版本号或时间戳控制,减少数据库层面的锁开销。 5. **监控与调优工具**: - 利用数据库内置视图(如`V$LOCKED_OBJECT`, `DBA_WAITERS`)识别锁争用热点。 - 使用AWR报告分析Top SQL,定位引起竞争的具体操作。 6. **引入队列机制或异步处理**: - 对于高并发写入场景,可以采用消息队列将请求串行化处理,减轻数据库压力。 ### 示例:查看行锁等待情况(Oracle) ```sql SELECT s.sid, s.serial#, s.username, s.program, l.type, l.id1, l.id2, l.lmode, l.request, l.block FROM v$session s JOIN v$lock l ON s.sid = l.sid WHERE type IN ('TM', 'TX'); ``` 此查询可以帮助识别当前系统中存在的锁信息,包括事务持有的锁类型、请求模式以及是否阻塞其他会话。 ### 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值