如何在虚拟线程中调用mysql

问题描述 投票:0回答:1

环境

  • mysql-connector-java:8.0.33
  • java版本:jdk21
  • springboot:3.2.1
  • 虚拟线程模式:true
  • 连接器池:hikari

问题

  • 看来 mysql-connector-java 有很多同步,固定了载体线程。
  • 如何解决这个问题?

跟踪堆栈信息

Thread[#93,ForkJoinPool-1-worker-4,5,CarrierThreads]
    java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:185)
    java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
    java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:631)
    java.base/java.lang.System$2.parkVirtualThread(System.java:2648)
    java.base/jdk.internal.misc.VirtualThreads.park(VirtualThreads.java:67)
    java.base/java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:408)
    java.base/sun.nio.ch.Poller.pollIndirect(Poller.java:137)
    java.base/sun.nio.ch.Poller.poll(Poller.java:102)
    java.base/sun.nio.ch.Poller.poll(Poller.java:87)
    java.base/sun.nio.ch.NioSocketImpl.park(NioSocketImpl.java:175)
    java.base/sun.nio.ch.NioSocketImpl.timedRead(NioSocketImpl.java:280)
    java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:304)
    java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:346)
    java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:796)
    java.base/java.net.Socket$SocketInputStream.read(Socket.java:1099)
    com.mysql.cj.protocol.ReadAheadInputStream.fill(ReadAheadInputStream.java:107)
    com.mysql.cj.protocol.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:150)
    com.mysql.cj.protocol.ReadAheadInputStream.read(ReadAheadInputStream.java:180) <== monitors:1
    java.base/java.io.FilterInputStream.read(FilterInputStream.java:119)
    com.mysql.cj.protocol.FullReadInputStream.readFully(FullReadInputStream.java:64)
    com.mysql.cj.protocol.a.SimplePacketReader.readHeaderLocal(SimplePacketReader.java:81)
    com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:63)
    com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:45)
    com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:52)
    com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:41)
    com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:54)
    com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:44)
    com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:576)
    com.mysql.cj.protocol.a.NativeProtocol.checkErrorMessage(NativeProtocol.java:762)
    com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:701)
    com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:156)
    com.mysql.cj.NativeSession.ping(NativeSession.java:733)
    com.mysql.cj.jdbc.ConnectionImpl.pingInternal(ConnectionImpl.java:1478)
    com.mysql.cj.jdbc.ConnectionImpl.isValid(ConnectionImpl.java:2516) <== monitors:1
    com.zaxxer.hikari.pool.PoolBase.isConnectionDead(PoolBase.java:157
mysql mysql-connector project-loom virtual-threads
1个回答
0
投票

一个非常简单的答案:不要在虚拟线程上调用 mySQL JDBC Connector 以避免固定。当然,除非您要重写 mySQL JDBC Connector。 Java 充满了

synchronized
,即使是像
java.util.concurrent.ConcurrentHashMap
这样流行且优秀的多线程工具也有它,不可能一夜之间用非固定替代方案取代所有
synchronized
和其他固定操作。 Project Loom 和虚拟线程还不够稳定和成熟,不足以保证如此大规模的重构。因此,您能做的最好的事情就是避免使用虚拟线程来频繁固定代码(虽然偶尔的固定可能是可以容忍的)

另一方面,如果虚拟线程被固定,它可能不会(或者不应该,如果不是 JDK bug)导致您的系统无限期挂起或死机或类似的情况。当该虚拟线程保持固定状态时,相应的 Carrier(平台)线程将被从 Carrier 线程池中排除。当固定动作时,例如

Thread.sleep
,完成,固定的螺纹应该变为未固定的。当然,固定会降低虚拟线程机器的性能,并且本身就是对它的滥用,但它不应该成为系统死亡的原因。 (除非你对事情“强调”到了不可能的程度,这可能是也可能不是你的个人情况)。

© www.soinside.com 2019 - 2024. All rights reserved.