首批通过分布式安全可靠测评,为关键业务系统打造
锁事件
更新时间:2026-04-07 20:57:20
临界区是高并发系统中与性能非常相关的一类资源,临界区需要通过锁进行保护。这里所说的锁,并不是用户语义上用于保证数据一致性的锁(悲观锁 or 乐观锁),而是物理实现上用于保护临界区的某种同步机制,在 OceanBase 数据库中,我们称它为 Latch。热点的临界区可能在并发访问时产生冲突,从而导致工作线程进入等待,记录这种等待,对于性能优化具有重要的指导意义。
锁的经典实现:调用者先尝试加锁,如果加不上,则进入 SPIN 过程,反复尝试加锁(避免过早放弃 CPU 而进入等待,对于短临界区非常有效),如果 SPIN 次数达到上限(称为 SPIN 上限)后,调用者仍然无法获得锁,则进入 WAIT 过程,将自己放入等待队列并让出 CPU。等待队列默认支持 FIFO,也可以支持其他优先级策略,例如读优先。
OceanBase 数据库提供了独立视图来展示所有锁事件相关的监控信息,目前已有 100 多个锁事件。锁事件本质是等待事件的一种,所有的锁事件都属于同一类等待事件(WAIT_CLASS 为 CONCURRENCY),但是锁事件相比一般的等待事件,具有更多的监控信息。每个锁事件都对应一个临界区,调用者可以通过锁事件的 SPIN 次数和调用次数之比来识别一个热点临界区,并决定是否采取优化手段。一个设计良好的并发系统,锁事件的 SPIN 次数和调用次数之比应该越小越好。
| 视图 | 展示内容 | 备注 |
|---|---|---|
GV$SYSTEM_EVENT |
租户级锁事件统计。 | where WAIT_CLASS='CONCURRENCY' and event like 'latch:%' |
GV$SESSION_EVENT |
会话级锁事件统计。 | where WAIT_CLASS='CONCURRENCY' and event like 'latch:%' |
GV$SESSION_WAIT |
会话级锁事件明细。 | where WAIT_CLASS='CONCURRENCY' and event like 'latch:%' |
GV$SESSION_WAIT_HISTORY |
会话级锁事件明细历史。 | where event like 'latch:%' |
GV$LATCH |
锁调用统计。 | |
锁事件本质上也是一种等待事件,所以上文介绍的等待事件相关的视图(主要包括等待统计和等待明细)也适用于锁事件,在查询条件中加上 where event like 'latch:%' 即可。例如查询租户级别的锁等待事件:
obclient> select * from gv$system_event where event like 'latch:%' limit 10;
+--------+-------------+----------+----------+-------------------------------------+---------------+-------------+-------------+-------------+----------------+-------------+----------------------+-------------------+
| CON_ID | SVR_IP | SVR_PORT | EVENT_ID | EVENT | WAIT_CLASS_ID | WAIT_CLASS# | WAIT_CLASS | TOTAL_WAITS | TOTAL_TIMEOUTS | TIME_WAITED | AVERAGE_WAIT | TIME_WAITED_MICRO |
+--------+-------------+----------+----------+-------------------------------------+---------------+-------------+-------------+-------------+----------------+-------------+----------------------+-------------------+
| 1 | xx.xx.xx.xx | 2882 | 15002 | latch: kvcache bucket wait | 104 | 4 | CONCURRENCY | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | 15003 | latch: default spin lock wait | 104 | 4 | CONCURRENCY | 103879 | 0 | 7504.0817 | 0.07223867865497358 | 75040817 |
| 1 | xx.xx.xx.xx | 2882 | 15004 | latch: default spin rwlock wait | 104 | 4 | CONCURRENCY | 1608 | 0 | 6.4665 | 0.004021455223880597 | 64665 |
| 1 | xx.xx.xx.xx | 2882 | 15005 | latch: default mutex wait | 104 | 4 | CONCURRENCY | 19210 | 0 | 62.2564 | 0.003240832899531494 | 622564 |
| 1 | xx.xx.xx.xx | 2882 | 15006 | latch: time wheel task lock wait | 104 | 4 | CONCURRENCY | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | 15007 | latch: time wheel bucket lock wait | 104 | 4 | CONCURRENCY | 5 | 0 | 0.0084 | 0.00168 | 84 |
| 1 | xx.xx.xx.xx | 2882 | 15008 | latch: election lock wait | 104 | 4 | CONCURRENCY | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | 15009 | latch: trans ctx lock wait | 104 | 4 | CONCURRENCY | 1419 | 0 | 3.6988 | 0.002606624383368569 | 36988 |
| 1 | xx.xx.xx.xx | 2882 | 15010 | latch: partition log lock wait | 104 | 4 | CONCURRENCY | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | 15011 | latch: plan cache pcv set lock wait | 104 | 4 | CONCURRENCY | 0 | 0 | 0 | 0 | 0 |
+--------+-------------+----------+----------+-------------------------------------+---------------+-------------+-------------+-------------+----------------+-------------+----------------------+-------------------+
10 rows in set (0.05 sec)
锁(Latch)事件除了等待统计和等待明细,还包括每类锁的调用次数和 SPIN 次数等。GV$LATCH 对此类信息进行了描述,例如:
obclient> select * from gv$latch limit 10;
+--------+-------------+----------+------+--------+--------+-------------------------+------+--------------+--------+--------+----------------+------------------+--------------+-----------+
| CON_ID | SVR_IP | SVR_PORT | ADDR | LATCH# | LEVEL# | NAME | HASH | GETS | MISSES | SLEEPS | IMMEDIATE_GETS | IMMEDIATE_MISSES | SPIN_GETS | WAIT_TIME |
+--------+-------------+----------+------+--------+--------+-------------------------+------+--------------+--------+--------+----------------+------------------+--------------+-----------+
| 1 | xx.xx.xx.xx | 2882 | NULL | 0 | 0 | latch wait queue lock | 0 | 223375312970 | 0 | 0 | 0 | 0 | 223375313928 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 1 | 0 | default spin lock | 0 | 30228076439 | 103935 | 0 | 2248146333 | 38281 | 32837812102 | 702 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 2 | 0 | default spin rwlock | 0 | 167079371683 | 1608 | 0 | 0 | 0 | 167110063485 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 3 | 0 | default mutex | 0 | 2846874203 | 19153 | 0 | 4140817202 | 0 | 7160839948 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 4 | 0 | kv cache bucket latch | 0 | 609838658953 | 0 | 0 | 0 | 0 | 609838670960 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 5 | 0 | time wheel task latch | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 6 | 0 | time wheel bucket latch | 0 | 23552766799 | 5 | 0 | 0 | 0 | 23552863465 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 7 | 0 | election latch | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 8 | 0 | trans ctx latch | 0 | 1421768682 | 1420 | 0 | 2096 | 1130 | 1426816069 | 0 |
| 1 | xx.xx.xx.xx | 2882 | NULL | 9 | 0 | partition log latch | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+--------+-------------+----------+------+--------+--------+-------------------------+------+--------------+--------+--------+----------------+------------------+--------------+-----------+
10 rows in set (0.04 sec)