Skip to content

使用 JDBC schemaless(AbstractConnection.write)写入时 Mach port(SEMAPHORE send rights)持续增长 #34557

@Qiaofanxing

Description

@Qiaofanxing

macOS 上使用 TDengine JDBC(通过 AbstractConnection.write(...) 进行 schemaless 写入)时,进程的 Mach port 数量持续增长,增长的主要是 send rights,并且通过 lsmp diff 发现新增对象类型为 SEMAPHORE
现象表现为:只要持续调用 schemaless 写入(每秒写19万个点),Mach port 的 send 权限数量会稳定上升(约每 2 秒增加 ~50 个),长期运行会导致端口空间不断膨胀,最终被系统 kill。

当不执行写入(不调用 taosCon.write(...))时,Mach port 不再增长,但是也不会减少。

另:最开始使用WS连接,但是没有长时间测试过,因为发现WS写入效率奇低,同样的数据写入需要2秒以上,改用 Native 写入只需要 40ms 左右。

补充:测试在Linux上没有出现此问题


To Reproduce

  1. 在 macOS 上运行一个 Java 服务/程序,使用 TDengine JDBC + Hikari 连接池,并在业务中持续进行 schemaless 写入(示例代码见下)。
  2. 获取进程 PID,例如 PID=61250
  3. 使用 lsmp 监控 Mach port 数量增长(每 2 秒打印一次):
while true; do
  ts="$(date '+%F %T')"
  sudo lsmp -p "$PID" | awk -v ts="$ts" '
    $1 ~ /^0x/ {
      total++
      if ($3 == "recv") r++
      if ($3 == "send") s++
      if ($3 == "send-once") so++
      if ($3 == "port-set") ps++
    }
    END { printf "%s total=%d recv=%d send=%d send-once=%d port-set=%d\n", ts, total, r, s, so, ps }'
  sleep 2
done
  1. 观察到 total/send 持续增长,例如(节选):
2026-02-11 14:13:02 total=13003 recv=182 send=12798 send-once=0 port-set=1
2026-02-11 14:13:07 total=13056 recv=182 send=12851 send-once=0 port-set=1
...
2026-02-11 14:19:44 total=23351 recv=182 send=23146 send-once=0 port-set=1
  1. send rights 做快照 diff,找出新增的 send rights 类型:
sudo lsmp -p "$PID" 2>/dev/null > /tmp/lsmp.1
sleep 5
sudo lsmp -p "$PID" 2>/dev/null > /tmp/lsmp.2

awk '$3=="send"{print $1, $2, $NF}' /tmp/lsmp.1 | sort > /tmp/send.1
awk '$3=="send"{print $1, $2, $NF}' /tmp/lsmp.2 | sort > /tmp/send.2

echo "NEW send rights:"
comm -13 /tmp/send.1 /tmp/send.2 | head -50

输出显示新增 send rights 的对象类型为 SEMAPHORE(节选):

NEW send rights:
0x0085e103 0x0d3c6389 SEMAPHORE
0x0085e203 0xca6f83b0 SEMAPHORE
0x0085e303 0x4dd6fc63 SEMAPHORE
...
  1. 使用 sample 采样进程堆栈,能看到大量线程在 TDengine native 库中等待信号量(节选):
sudo sample $PID 5 -file /tmp/sample.txt
# 查看关键堆栈
nl -ba /tmp/sample.txt | sed -n '1460,1540p'
nl -ba /tmp/sample.txt | sed -n '4960,5060p'

堆栈中可见 libtaosnative.3.4.0.2.dylibtsem_wait/tsem_timewait 调用链进入 GCD semaphore wait:

  • taosProcessSchedQueue / monitorThreadFunc / ctgUpdateThreadFunc / ... (in libtaosnative.3.4.0.2.dylib)
  • tsem_wait / tsem_timewait (in libtaosnative.3.4.0.2.dylib)
  • _dispatch_semaphore_wait_slow (in libdispatch.dylib)
  • semaphore_wait_trap / semaphore_timedwait_trap (in libsystem_kernel.dylib)

并且在 Java JNI 写入路径中看到:

  • Java_com_taosdata_jdbc_TSDBJNIConnector_schemalessInsertImp (in libtaos.3.4.0.2.dylib)
  • schemalessInsert / taos_schemaless_insert* (in libtaosnative.3.4.0.2.dylib)
  • tsem_wait -> _dispatch_semaphore_wait_slow -> semaphore_wait_trap
  1. 对照实验:不执行写入(不调用 taosCon.write(...))时,Mach port 数量不增长。

Environment

  • OS: macOS 26.2

  • Memory / CPU / Disk: M4pro 24G

  • JDK: JDK 1.8

  • TDengine Version: 3.4.0

  • 进程采样中显示 native 库为:libtaosnative.3.4.0.2.dyliblibtaos.3.4.0.2.dylib

  • 连接池:HikariCP

  • 使用方式:Spring JdbcTemplate.execute(ConnectionCallback) 获取连接并 unwrap(AbstractConnection.class) 调用 write


Additional Context

业务侧调用代码(节选)

public void writeSchemaless(String[] lines) {
    if (lines == null || lines.length == 0) return;

    tdengineJdbcTemplate.execute((ConnectionCallback<Object>) con -> {
        try {
            if (con.isWrapperFor(AbstractConnection.class)) {
                AbstractConnection taosCon = con.unwrap(AbstractConnection.class);
                taosCon.write(lines,
                    SchemalessProtocolType.LINE,
                    SchemalessTimestampType.MILLI_SECONDS);
            } else {
                throw new SQLException("Connection is not an instance of AbstractConnection");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return null;
    });
}

关键观察

  • lsmp 监控显示 send rights 与 total 持续增长(增长速率稳定)。
  • lsmp diff 显示新增 send rights 的对象类型为 SEMAPHORE
  • sample 堆栈中大量线程在 libtaosnative.3.4.0.2.dylibtsem_wait/tsem_timewait_dispatch_semaphore_wait_slowsemaphore_wait_trap
  • A/B 对照:不调用写入则 Mach port 不涨。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions