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支持进行处理。

results matching ""

    No results matching ""