开发者社区> 问答> 正文

使用flyway ,再连接数据库的时候报如下错误

com.alibaba.druid.pool.DruidDataSource : discard connection

java.sql.SQLSyntaxErrorException: Access denied; you need (at least one of) the SUPER or SET_USER_ID privilege(s) for this operation

展开
收起
游客bpykrimjyrxg4 2020-03-24 21:57:30 1672 0
1 条回答
写回答
取消 提交回答
  • 首先搜了下druid 官网 FAQ
    https://github.com/alibaba/druid/wiki/常见问题
    发现是druid有对连接泄露进行监控处理
    
    https://github.com/alibaba/druid/wiki/连接泄漏监测
    https://github.com/alibaba/druid/issues/872
    我这边没有配对监控,直接是从日志中看到的,有相应的线程栈信息,可以方便排查。
    
    public DruidPooledConnection getConnectionDirect(long maxWaitMillis) throws SQLException {
            int notFullTimeoutRetryCnt = 0;
    
            DruidPooledConnection poolableConnection;
            while(true) {
                while(true) {
                    try {
               
                    Connection realConnection = poolableConnection.getConnection();
                    this.discardConnection(realConnection);
                } else {
                    Connection realConnection = poolableConnection.getConnection();
                    if(realConnection.isClosed()) {
                        this.discardConnection((Connection)null);
                    } else {
                        if(!this.isTestWhileIdle()) {
                            break;
                        }
    
                        long currentTimeMillis = System.currentTimeMillis();
                        long lastActiveTimeMillis = poolableConnection.getConnectionHolder().getLastActiveTimeMillis();
                        long idleMillis = currentTimeMillis - lastActiveTimeMillis;
                        long timeBetweenEvictionRunsMillis = this.getTimeBetweenEvictionRunsMillis();
                        if(timeBetweenEvictionRunsMillis <= 0L) {
                            timeBetweenEvictionRunsMillis = 60000L;
                        }
    
                        if(idleMillis < timeBetweenEvictionRunsMillis) {
                            break;
                        }
    
                        this.discardConnection(realConnection);
                    }
                }
            }
    
            if(this.isRemoveAbandoned()) {
                StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
                poolableConnection.setConnectStackTrace(stackTrace);
                poolableConnection.setConnectedTimeNano();
                poolableConnection.setTraceEnable(true);
                Map var21 = this.activeConnections;
                synchronized(this.activeConnections) {
                    this.activeConnections.put(poolableConnection, PRESENT);
                }
            }
    
            if(!this.isDefaultAutoCommit()) {
                poolableConnection.setAutoCommit(false);
            }
    
            return poolableConnection;
        }
    
    这个连接泄露不会导致OOM,因为druid会去主动detroy这些未关闭的连接,也就是上面日志中的错误信息
    
    现在知道是有数据库连接未关闭,但是代码中并没有去管理数据库连接池,都是交给了Spring去管理的呢,而且不是每个数据库操作都会有问题,而是特定的数据库操作有问题
    
    开启debug日志
    

    2018-01-23 21:08:35,760 DEBUG [org.springframework.data.redis.core.RedisConnectionUtils] - Opening RedisConnection 2018-01-23 21:08:35,761 DEBUG [org.springframework.data.redis.core.RedisConnectionUtils] - Closing Redis Connection 2018-01-23 21:08:35,762 DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession 2018-01-23 21:08:35,762 DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba28a19] was not registered for synchronization because synchronization is not active 2018-01-23 21:08:35,765 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource 2018-01-23 21:08:35,765 DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.taobao.tddl.matrix.jdbc.TConnection@24f6de0] will not be managed by Spring 2018-01-23 21:08:35,766 DEBUG [com.taobao.tddl.group.jdbc.TGroupConnection] - [TDDL] dataSourceIndex=GroupIndex [index=0, failRetry=false], tddl version: 5.1.7 2018-01-23 21:08:35,810 DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ba28a19] 2018-01-23 21:08:35,810 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource

    这里接可以看出阿里的开源软件距离工业级还有距离,Spring的可以清楚的看到连接释放与返回,而Druid并没有

    因为这个是和特定的SQL有关系,所有看下具体的这个SQL操作
    
     @Options(statementType = StatementType.CALLABLE)
        @Insert("<script> " +  
                "</script>")
     int saveDemo(Demo demo);
    这个是之前人留下的,这种写法目前在项目组不是很常见了,没有实现代码与SQL语句分离,不是很提倡。
    这边的StatementType为Callable,看起来比奇怪,一般CallableStatement由于数据库存储过程的操作,显然这个语句不是这么调用存储过程。不知道前任为什么这么写,所以首先干掉了这个StatementType.CALLABLE参数。
    
    结果果然出错了,调用的时候报错,一个好笑的错误,没有使用auto generate id,却调用了。
    
    这个应该是MySQL 5.7 driver的一个bug,前任为了避免这个问题,使用CallableStatement绕过去了
    
    Caused by: Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate() or Connection.prepareStatement().
    at com.taobao.tddl.repo.mysql.handler.PutMyHandlerCommon.handle(PutMyHandlerCommon.java:52)
    at com.taobao.tddl.executor.AbstractGroupExecutor.executeInner(AbstractGroupExecutor.java:59)
    at com.taobao.tddl.executor.AbstractGroupExecutor.execByExecPlanNode(AbstractGroupExecutor.java:40)
    at com.taobao.tddl.executor.TopologyExecutor.execByExecPlanNode(TopologyExecutor.java:59)
    at com.taobao.tddl.executor.MatrixExecutor.execByExecPlanNode(MatrixExecutor.java:282)
    
    所以先改成xml方式验证下,xml默认是PreparedStatement,然后看下是否还能发生错误
    

    发现没有了,所以问题的原因就是CallableStatement造成的

    2020-04-15 23:11:08
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
DTCC 2022大会集锦《云原生一站式数据库技术与实践》 立即下载
阿里云瑶池数据库精要2022版 立即下载
2022 DTCC-阿里云一站式数据库上云最佳实践 立即下载