2.35 堆外内存泄露监控
2.35.1 介绍
支持版本:
>=3.22.11.0
简介:
dble 使用了direct memory(堆外内存)用于加速io读写,代价是 dble 需要额外处理堆外内存的分配和释放。如果因为程序异常可能导致堆外内存不被释放,这些堆外内存就被泄露了。
当越来越多的堆外内存被泄露,后果是堆内内存池满了,接着 dble 启用堆内内存代替堆外内存,从而影响 dble 的性能。
堆外内存泄露监控 功能可以用于监控堆外内存的释放和监控,便于发现泄漏点,从而可以进行相应的修复。
何时应开启:
当发现已使用的 direct memory 较大(几百MB)或者持续增长时,且在业务低峰也没有降下来。此时应该开启该监控调查增长的原因。
已使用的 direct memory 可以通过show @@directmemory
命令的 DIRECT_MEMORY_POOL_USED
字段查看。
性能:
该功能主要用于定位故障点,不应该长期开启,当开启此功能后会存在约20%的性能下降(不同机器不一样),需要为内存、cpu预留20%的空间。
术语定义:
每一块分配的堆外内存简称为buffer。
2.35.2 原理
开启开关后,每次分配的堆外内存都会被记录在表dble_memory_resident中。当该内存被回收后,表会删除相同 id 的记录。
2.35.3 bootstrap.cnf中的相关配置
# whether enable the memory buffer monitor
#-DenableMemoryBufferMonitor=0
#-DenableMemoryBufferMonitorRecordPool=1
2.35.4 管理端命令
2.35.4.1 enable @@memory_buffer_monitor
开启监控
mysql> enable @@memory_buffer_monitor;
Query OK, 1 row affected (4.26 sec)
2.35.4.2 disable @@memory_buffer_monitor
关闭监控并回收数据。
mysql> disable @@memory_buffer_monitor;
Query OK, 1 row affected (0.01 sec)
disable MemoryBufferMonitor success
2.35.4.3 select * from dble_memory_resident \G
显示当前未回收的 buffer。该表的字段含义可查看【管理端元数据库】章节。
开启了监控该表才有效。且开关开启后的内存泄露才有可能记录,开启前的已经出现的内存泄露将永远无法被记录到。
为避免误解,buffer 存活时间不到 1s 的 不被记录在表内,这些 buffer 通常很快就被释放。
mysql> select * from dble_memory_resident \G
*************************** 1. row ***************************
id: 140185807364096
alive_second: 29.892
stacktrace:
com.actiontech.dble.buffer.MemoryBufferMonitor.addRecord(MemoryBufferMonitor.java:80)
com.actiontech.dble.buffer.DirectByteBufferPool.allocate(DirectByteBufferPool.java:58)
com.actiontech.dble.net.connection.AbstractConnection.allocate(AbstractConnection.java:431)
com.actiontech.dble.net.connection.AbstractConnection.findReadBuffer(AbstractConnection.java:529)
com.actiontech.dble.net.connection.FrontendConnection.findReadBuffer(FrontendConnection.java:358)
com.actiontech.dble.net.impl.nio.NIOSocketWR.asyncRead(NIOSocketWR.java:358)
com.actiontech.dble.services.mysqlauthenticate.MySQLFrontAuthService.register(MySQLFrontAuthService.java:61)
com.actiontech.dble.net.connection.AbstractConnection.register(AbstractConnection.java:601)
buffer_type: POOL
allocate_size: 4096
allocate_time: 2022-12-07 17:21:39.901
sql: <<FRONT>>
1 row in set (0.00 sec)
2.35.5 使用方法
开启开关,这样之后的泄露将被记录。 开启后维持一段时间后,观察 buffer_type=NORMAL 的记录(即非常驻内存),可以通过以下 sql 观察:
mysql> select * from dble_memory_resident where buffer_type="NORMAL"\G
Empty set (0.02 sec)
- 如果以上 sql 产生了结果且 alive_second较小,可能是正常的业务分配,可以先等等看看记录会不会回收
- 如果以上 sql 产生了结果且 alive_second较大(即 buffer 长时间没回收),可联系dble支持进行处理。
- 如果以上 sql 没有结果,同时这段时间内
DIRECT_MEMORY_POOL_USED
也没有上升,这说明这段时间泄漏点没有触发或者不存在泄露。需要多尝试不同的业务和场景来找到泄漏点。 - 如果以上 sql 没有结果,同时这段时间内
DIRECT_MEMORY_POOL_USED
也上升了,此时可能存在常驻内存泄露。可以发送dble_memory_resident表的结果并联系dble支持进行处理。