nebula-contrib / ngbatis

NGBATIS is a database ORM framework base NebulaGraph + spring-boot, which takes advantage of the mybatis’ fashion development, including some de-factor operations in single table and vertex-edge, like mybatis-plus. NGBATIS 是一款针对 NebulaGraph + Springboot 的数据库 ORM 框架。借鉴于 MyBatis 的使用习惯进行开发。https://graph-cn.github.io/ngbatis-docs/
https://nebula-contrib.github.io/ngbatis/
Apache License 2.0
124 stars 42 forks source link

BatchInsert java.lang.StackOverflowError: null #31

Open btbox opened 2 years ago

btbox commented 2 years ago
Unexpected exception occurred invoking async method: public void com.box.modules.work.graph_import.async.GraphImportAsync.asyncBatchInsertGraph(java.lang.String,java.lang.String,java.lang.String,java.util.Map,java.util.List)

java.lang.StackOverflowError: null
    at com.box.modules.work.graph_import.service.impl.GraphBaseApiImpl.batchInsertVertex(GraphBaseApiImpl.java:126)
    at com.box.modules.work.graph_import.async.GraphImportAsync.asyncBatchInsertGraph(GraphImportAsync.java:45)
    at com.box.modules.work.graph_import.async.GraphImportAsync$$FastClassBySpringCGLIB$$5ed53427.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
btbox commented 2 years ago

很奇怪的是,我之前是2000为一次batch插入是发生这个异常,换成 1W一次batchInsert没有问题

btbox commented 2 years ago
<insert id="batchInsertVertex" >
        INSERT VERTEX ${tagName}
         (
            @for ( param in params ) {
                ${param}${paramLP.last?"":"," }
            @}
         )
        VALUES
        ${dataStr};
    </insert>
CorvusYe commented 2 years ago

感觉有可能是因为2000条一页的时候开的线程数太多了?

btbox commented 2 years ago

但是我用的是线程池,6 core, 12 线程 队列 是 9999

如上所述,450页的话,就会循环450次 @Async里面的线程方法去batchInsert

@Bean(name = "graphAsyncImportExecutor")
    public Executor graphAsyncImportExecutor() {
        //在这里修改
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(Runtime.getRuntime().availableProcessors());
        //配置最大线程数
        executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
        //配置队列大小
        executor.setQueueCapacity(queueCapacity);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix(namePrefix);
        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
CorvusYe commented 2 years ago

既然线程有不大的上限,所开线程一致的话,按道理2000一次所占用的内存会更小才对,是有些反直觉。 不好意思,刚刚看错了... 还以为是OutOfMemoryException。 报错有 Cause by 信息吗

btbox commented 2 years ago

java.lang.StackOverflowError: null at com.box.modules.work.graph_import.service.impl.GraphBaseApiImpl.batchInsertVertex(GraphBaseApiImpl.java:126) at com.box.modules.work.graph_import.async.GraphImportAsync.asyncBatchInsertGraph(GraphImportAsync.java:45) at com.box.modules.work.graph_import.async.GraphImportAsync$$FastClassBySpringCGLIB$$5ed53427.invoke() at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

CorvusYe commented 2 years ago

xml 看上去没有问题,如果dataStr每条写入值的栏位跟params一致,应该不会有太大问题。