当前位置: 首页 > 知识库问答 >
问题:

java - springboot项目中,用atomikos做的多数据源配置,某一个数据库,白天的时候访问非常慢,深夜访问就正常?

宗政文彬
2023-06-28

项目连接了3个数据库,分别是 base1,base2,base3;
base1,base2白天晚上访问都正常;
base3,白天访问大部分都是超时,偶尔能通,还非常慢,到了晚上就可以正常访问了;
三个数据库数据结构,接口配置一模一样,只是用来区分不同的国家而已;
因为做了实时大屏看板,所以会频繁的请求该项目,并且会不停的切换数据源;会不会是数据源的通用配置有点小了?

数据源的通用配置如下:

    <bean id="dataSourceConfig" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true">
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="poolSize" value="10"/>
        <property name="maxPoolSize" value="20"/>
        <property name="minPoolSize" value="5"/>
        <property name="maxIdleTime" value="5"/>
        <property name="maxLifetime" value="60"/>
        <property name="borrowConnectionTimeout" value="60"/>
        <property name="testQuery" value="SELECT 'x' from dual"/>
        <property name="isLoad" value="${datasource.loadDB.haier}" />
    </bean>

AtomikosDataSourceBean代码如下

/**
 * Copyright (C) 2000-2013 Atomikos <info@atomikos.com>
 *
 * This code ("Atomikos TransactionsEssentials"), by itself,
 * is being distributed under the
 * Apache License, Version 2.0 ("License"), a copy of which may be found at
 * http://www.atomikos.com/licenses/apache-license-2.0.txt .
 * You may not use this file except in compliance with the License.
 *
 * While the License grants certain patent license rights,
 * those patent license rights only extend to the use of
 * Atomikos TransactionsEssentials by itself.
 *
 * This code (Atomikos TransactionsEssentials) contains certain interfaces
 * in package (namespace) com.atomikos.icatch
 * (including com.atomikos.icatch.Participant) which, if implemented, may
 * infringe one or more patents held by Atomikos.
 * It should be appreciated that you may NOT implement such interfaces;
 * licensing to implement these interfaces must be obtained separately from Atomikos.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package com.atomikos.jdbc;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.XADataSource;

import com.atomikos.beans.PropertyUtils;
import com.atomikos.datasource.RecoverableResource;
import com.atomikos.datasource.xa.jdbc.JdbcTransactionalResource;
import com.atomikos.icatch.system.Configuration;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.util.ClassLoadingHelper;

 /**
 * The preferred class for using Atomikos connection pooling. Use an instance of
 * this class if you want to use Atomikos JTA-enabled connection pooling. All
 * you need to do is construct an instance and set the required properties as
 * outlined below. The resulting bean will automatically register with the
 * transaction service (for recovery) and take part in active transactions.
 * All SQL done over connections (gotten from this class) will participate in JTA transactions.
 */

public class AtomikosDataSourceBean 
extends AbstractDataSourceBean
{
    private static final Logger LOGGER = LoggerFactory.createLogger(AtomikosDataSourceBean.class);
    
    
    private static final long serialVersionUID = 1L;
    
    private Properties xaProperties = null;
    private String xaDataSourceClassName;
    private transient XADataSource xaDataSource;
    public AtomikosDataSourceBean() 
    {
        this.xaProperties = new Properties();
    }
    
    protected String printXaProperties()
    {
        StringBuffer ret = new StringBuffer();
        if ( xaProperties != null ) {
            Enumeration it = xaProperties.propertyNames();
            ret.append ( "[" );
            boolean first = true;
            while ( it.hasMoreElements() ) {
                if ( ! first ) ret.append ( "," );
                String name = ( String ) it.nextElement();
                String value = xaProperties.getProperty( name);
                ret.append ( name ); ret.append ( "=" ); ret.append ( value );
                first = false;
            }
            ret.append ( "]" );
        }
        return ret.toString();
    }
    
    /**
     * Gets the properties used to
     * configure the XADataSource.  
     */
    
    public Properties getXaProperties()
    {
        return xaProperties;
    }

    /**
     * Sets the properties (name,value pairs) used to
     * configure the XADataSource. Required, unless you call setXaDataSource directly.
     * 
     * @param xaProperties 
     * 
     *
     */
    public void setXaProperties ( Properties xaProperties ) 
    {
        this.xaProperties = xaProperties;
        Map<String,String> db = new HashMap<String,String>();
        db.put("url", xaProperties.getProperty("URL"));
        db.put("user", xaProperties.getProperty("user"));
        db.put("password", xaProperties.getProperty("password"));
        //将子类的数据库信息传给父类使用
        super.dbInfo = db;
    }

    /**
     * Get the XADataSource class name.
     */
    public String getXaDataSourceClassName() 
    {
        return xaDataSourceClassName;
    }

    /**
     * Sets the fully qualified underlying XADataSource class name. Required, unless you 
     * call setXaDataSource directly.
     * 
     * @param xaDataSourceClassName
     */
    public void setXaDataSourceClassName ( String xaDataSourceClassName ) 
    {
        this.xaDataSourceClassName = xaDataSourceClassName;
    }
    
    /**
     * Gets the configured XADataSource (if any).
     * @return The instance, or null if none.
     */
    
    public XADataSource getXaDataSource()
    {
        return xaDataSource;
    }
    
    /**
     * Sets the XADataSource directly - instead of providing the xaDataSourceClassName and xaProperties.
     * @param xaDataSource
     */
    public void setXaDataSource(XADataSource xaDataSource)
    {
        this.xaDataSource = xaDataSource;
    }
    
    
    protected com.atomikos.datasource.pool.ConnectionFactory doInit() throws Exception 
    {
        if (xaDataSource == null)
        {
            if (xaDataSourceClassName == null)
                throwAtomikosSQLException("Property 'xaDataSourceClassName' cannot be null");
            if (xaProperties == null)
                throwAtomikosSQLException("Property 'xaProperties' cannot be null");
        }
        
        
        if ( LOGGER.isInfoEnabled() ) LOGGER.logInfo(
                this + ": initializing with [" +
                " xaDataSourceClassName=" + xaDataSourceClassName + "," +
                " uniqueResourceName=" + getUniqueResourceName() + "," +
                " maxPoolSize=" + getMaxPoolSize() + "," +
                " minPoolSize=" + getMinPoolSize() + "," +
                " borrowConnectionTimeout=" + getBorrowConnectionTimeout() + "," +
                " maxIdleTime=" + getMaxIdleTime() + "," +
                " reapTimeout=" + getReapTimeout() + "," +
                " maintenanceInterval=" + getMaintenanceInterval() + "," +
                " testQuery=" + getTestQuery() + "," +
                " xaProperties=" + printXaProperties() + "," +
                " loginTimeout=" + getLoginTimeout() + "," + 
                " maxLifetime=" + getMaxLifetime() +
                "]"
                );
        
        
            if (xaDataSource == null)
            {
                Class xadsClass = null;
                try {
                    xadsClass = ClassLoadingHelper.loadClass ( getXaDataSourceClassName() );
                } catch ( ClassNotFoundException nf ) {
                    AtomikosSQLException.throwAtomikosSQLException ( "The class '" + getXaDataSourceClassName() +
                            "' specified by property 'xaDataSourceClassName' could not be found in the classpath. Please make sure the spelling is correct, and that the required jar(s) are in the classpath." , nf );
                     
                }
                Object driver =  xadsClass.newInstance();
                if ( ! ( driver instanceof XADataSource ) ) {
                    AtomikosSQLException.throwAtomikosSQLException (
                             "The class '" + getXaDataSourceClassName() +
                                "' specified by property 'xaDataSourceClassName' does not implement the required interface javax.jdbc.XADataSource. Please make sure the spelling is correct, and check your JDBC driver vendor's documentation." 
                    );
                }
                xaDataSource = (XADataSource) driver;
                xaDataSource.setLoginTimeout ( getLoginTimeout() );
                xaDataSource.setLogWriter ( getLogWriter() );
                PropertyUtils.setProperties(xaDataSource, xaProperties );
            }
            
            JdbcTransactionalResource tr = new JdbcTransactionalResource(getUniqueResourceName() , xaDataSource);
            com.atomikos.datasource.pool.ConnectionFactory cf = new com.atomikos.jdbc.AtomikosXAConnectionFactory(xaDataSource, tr, this);
            Configuration.addResource ( tr );
            
            return cf;
    }
    
    protected void doClose() 
    {
        RecoverableResource res = Configuration.getResource ( getUniqueResourceName() );
        if ( res != null ) {
            Configuration.removeResource ( getUniqueResourceName() );
            //fix for case 26005
            res.close();
        }
    }    

    public String toString() 
    {
        String ret = "AtomikosDataSoureBean";
        String name = getUniqueResourceName();
        if ( name != null ) {
            ret = ret + " '" + name + "'";
        }
        return ret;
    }


    protected boolean isAssignableFromWrappedVendorClass(Class<?> iface) {
        boolean ret = false;
         if (xaDataSource != null ) { 
             ret = iface.isAssignableFrom(xaDataSource.getClass());
         }
         return ret;
    }

    @Override
    protected Object unwrapVendorInstance() {
        return xaDataSource;
    }


}

AbstractDataSourceBean代码如下

/**
 * Copyright (C) 2000-2010 Atomikos <info@atomikos.com>
 *
 * This code ("Atomikos TransactionsEssentials"), by itself,
 * is being distributed under the
 * Apache License, Version 2.0 ("License"), a copy of which may be found at
 * http://www.atomikos.com/licenses/apache-license-2.0.txt .
 * You may not use this file except in compliance with the License.
 *
 * While the License grants certain patent license rights,
 * those patent license rights only extend to the use of
 * Atomikos TransactionsEssentials by itself.
 *
 * This code (Atomikos TransactionsEssentials) contains certain interfaces
 * in package (namespace) com.atomikos.icatch
 * (including com.atomikos.icatch.Participant) which, if implemented, may
 * infringe one or more patents held by Atomikos.
 * It should be appreciated that you may NOT implement such interfaces;
 * licensing to implement these interfaces must be obtained separately from Atomikos.
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package com.atomikos.jdbc;

import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;

import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.atomikos.datasource.pool.ConnectionFactory;
import com.atomikos.datasource.pool.ConnectionPool;
import com.atomikos.datasource.pool.ConnectionPoolException;
import com.atomikos.datasource.pool.ConnectionPoolProperties;
import com.atomikos.datasource.pool.CreateConnectionException;
import com.atomikos.datasource.pool.PoolExhaustedException;
import com.atomikos.icatch.HeuristicMessage;
import com.atomikos.icatch.StringHeuristicMessage;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.util.IntraVmObjectFactory;
import com.atomikos.util.IntraVmObjectRegistry;

 /**
  * 
  * 
  * Abstract data source bean with generic functionality.
  * 
  *
  */

public abstract class AbstractDataSourceBean 
implements HeuristicDataSource, ConnectionPoolProperties, Referenceable, Serializable
{
    private static final Logger LOGGER = LoggerFactory.createLogger(AbstractDataSourceBean.class);
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractDataSourceBean.class);
    
    static final int DEFAULT_ISOLATION_LEVEL_UNSET = -1;
    static final int DEFAULT_POOL_SIZE = 1;

    private int minPoolSize = DEFAULT_POOL_SIZE;
    private int maxPoolSize = DEFAULT_POOL_SIZE;
    private int borrowConnectionTimeout = 30;
    private int reapTimeout = 0;
    private int maxIdleTime = 60;
    private String testQuery;
    private int maintenanceInterval = 60;
    private int loginTimeout;
    private transient ConnectionPool connectionPool;
    private transient PrintWriter logWriter;
    private String resourceName;
    protected Map<String,String> dbInfo;
    private String isLoad;//记录该数据库是否需要加载

    private int defaultIsolationLevel = DEFAULT_ISOLATION_LEVEL_UNSET;
    private int maxLifetime;
    
    protected void throwAtomikosSQLException ( String msg ) throws AtomikosSQLException 
    {
        throwAtomikosSQLException ( msg , null );
    }
    
    protected void throwAtomikosSQLException ( String msg , Throwable cause ) throws AtomikosSQLException 
    {
        AtomikosSQLException.throwAtomikosSQLException ( msg  , cause );
    }

    /**
     * Gets the minimum size of the pool. 
     */
    public int getMinPoolSize() {
        return minPoolSize;
    }

    /**
     * Sets the minimum pool size. The amount of pooled connections won't go
     * below that value. The pool will open this amount of connections during
     * initialization. Optional, defaults to 1.
     * 
     * @param minPoolSize
     */
    public void setMinPoolSize(int minPoolSize) {
        this.minPoolSize = minPoolSize;
    }

    /**
     * Get the maximum pool size. 
     */
    public int getMaxPoolSize() {
        return maxPoolSize;
    }

    /**
     * Sets the maximum pool size. The amount of pooled connections won't go
     * above this value. Optional, defaults to 1.
     * 
     * @param maxPoolSize
     */
    public void setMaxPoolSize(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
    }

    /**
     * Sets both the minimal and maximal pool size. 
     * Required if the maxPoolSize is not set. Overrides any minPoolSize
     * or maxPoolSize settings you might have configured before!
     */
    public void setPoolSize(int poolSize) {
        this.minPoolSize = poolSize; 
        this.maxPoolSize = poolSize;
    }

    /**
     * Get the maximum amount of time in seconds the pool will block
     * waiting for a connection to become available in the pool when it
     * is empty. 
     */
    public int getBorrowConnectionTimeout() {
        return borrowConnectionTimeout;
    }

    /**
     * Sets the maximum amount of time in seconds the pool will block
     * waiting for a connection to become available in the pool when it
     * is empty. Optional.
     * 
     * @param borrowConnectionTimeout The time in seconds. Zero or negative means no waiting at all.
     * Defaults to 30 seconds.
     */
    public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
        this.borrowConnectionTimeout = borrowConnectionTimeout;
    }

    /**
     * Get the amount of time in seconds the connection pool will allow a connection
     * to be borrowed before claiming it back.
     */
    public int getReapTimeout() {
        return reapTimeout;
    }

    /**
     * Sets the amount of time (in seconds) that the connection pool will allow a connection
     * to be in use, before claiming it back. Optional. 
     * 
     * @param reapTimeout The timeout in seconds. Zero means unlimited. Note that this value is 
     * only an indication; the pool will check regularly as indicated by the maintenanceInteval property.
     * Default is 0 (no timeout). 
     */
    public void setReapTimeout(int reapTimeout) {
        this.reapTimeout = reapTimeout;
    }

    /**
     * Sets the maintenance interval for the pool maintenance thread.
     * Optional. 
     * 
     * @param maintenanceInterval The interval in seconds. If not set or not positive then the pool's default (60 secs) will be used.
     */
    public void setMaintenanceInterval(int maintenanceInterval) {
        this.maintenanceInterval = maintenanceInterval;
    }

    /**
     * Gets the maintenance interval as set.
     */
    public int getMaintenanceInterval() {
        return this.maintenanceInterval;
    }

    /**
     * Gets the maximum amount of time in seconds a connection can stay in the pool
     * before being eligible for being closed during pool shrinking.
     */
    public int getMaxIdleTime() {
        return maxIdleTime;
    }

    /**
     * Sets the maximum amount of seconds that unused excess connections should stay in the pool. Optional.
     * 
     * Note: excess connections are connections that are created above the minPoolSize limit.
     * 
     * @param maxIdleTime The preferred idle time for unused excess connections. Note that this value is 
     * only an indication; the pool will check regularly as indicated by the maintenanceInteval property.
     * The default is 60 seconds.
     */
    public void setMaxIdleTime(int maxIdleTime) {
        this.maxIdleTime = maxIdleTime;
    }
    
    /**
     * Sets the maximum amount of seconds that a connection is kept in the pool before 
     * it is destroyed automatically. Optional, defaults to 0 (no limit).
     * @param maxLifetime
     */
    public void setMaxLifetime(int maxLifetime) {
        this.maxLifetime = maxLifetime;
    }
    
    /**
     * Gets the maximum lifetime in seconds.
     * 
     */
    public int getMaxLifetime() {
        return maxLifetime;
    }

    /**
     * Gets the SQL query used to test a connection before returning it. 
     */
    public String getTestQuery() {
        return testQuery;
    }

    /**
     * Sets the SQL query or statement used to validate a connection before returning it. Optional. 
     * 
     * @param testQuery - The SQL query or statement to validate the connection with. Note that 
     * although you can specify updates here, these will NOT be part of any JTA transaction!
     */
    public void setTestQuery(String testQuery) {
        this.testQuery = testQuery;
    }

    public int poolAvailableSize() {
        return connectionPool.availableSize();
    }

    public int poolTotalSize() {
        return connectionPool.totalSize();
    }

    public PrintWriter getLogWriter() throws SQLException {
        return logWriter;
    }

    public int getLoginTimeout() throws SQLException {
        return loginTimeout;
    }

    public void setLogWriter(PrintWriter out) throws SQLException {
        this.logWriter = out;
    }

    public void setLoginTimeout(int seconds) throws SQLException {
        this.loginTimeout = seconds;
    }

    public synchronized void init() throws AtomikosSQLException
    {
        /*2021年3月29日13:37:03增加动态加载数据源,来适配Romania和国内工厂一套代码,通过isLoad属性指定加载 */
        if(StringUtils.isBlank(this.isLoad) || "false".equals(this.isLoad)) {
            log.info("[{}]数据源加载配置为[{}],跳过加载",this.resourceName,this.isLoad);
            return;
        }else {
            log.info("[{}]数据源加载配置为[{}],正常加载",this.resourceName,this.isLoad);
        }
        if ( LOGGER.isInfoEnabled() ) {
            LOGGER.logInfo ( this + ": init..." );
        }
        //目前连接池存在连接
        if (connectionPool != null) {
            log.info("connectionPool不为null,存在连接");
            LOGGER.logInfo("测试log日志是否打印1");
            return;
        }else {
            log.info("connectionPool为null,不存在连接");
            LOGGER.logInfo("测试log日志是否打印2");
            //数据库名称
            String dbName = this.resourceName;
            String driver="com.mysql.jdbc.Driver";//获取mysql数据库的驱动类
            Connection conn = null;
            try {
                Class.forName(driver);
                LOGGER.logInfo("dbInfo信息:"+dbInfo.toString());
                long startTime = System.currentTimeMillis();
                conn = DriverManager.getConnection(dbInfo.get("url")+"&connectTimeout=10000",dbInfo.get("user"),dbInfo.get("password"));
                long endTime = System.currentTimeMillis();
                log.info("conn run time(毫秒):"+(endTime - startTime));
                if(conn != null) {
                    if(conn.isClosed()) {
                        log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo));
                        LOGGER.logInfo("数据库连接检测异常1");
                        return;//假如打不开数据库链接则跳过初始化数据库
                    }else {
                        LOGGER.logInfo("数据库连接检测正常1");
                        //说明数据库可以正常连接,关闭测试连接
                        conn.close();
                        log.info("[{}]数据库连接检测正常",dbName);
                    }
                }else {
                    LOGGER.logInfo("数据库连接检测异常2");
                    log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo));
                    return;
                }
            } catch (SQLException e) {
                LOGGER.logInfo("数据库连接检测异常3");
                log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo),e);
                //出现异常则跳过初始化数据库
                return;
            } catch (ClassNotFoundException e) {
                log.error("未找到数据库驱动[{}]",driver,e);
                //出现异常则跳过初始化数据库
                return;
            }finally {
                if(null != conn) {
                    try {
                        conn.close();
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }
            }
        }
        if ( maxPoolSize < 1 ) {
            throwAtomikosSQLException("Property 'maxPoolSize' must be greater than 0, was: " + maxPoolSize);
        }
        if ( minPoolSize < 0 || minPoolSize > maxPoolSize ) {
            throwAtomikosSQLException("Property 'minPoolSize' must be at least 0 and at most maxPoolSize, was: " + minPoolSize);
        }
        if ( getUniqueResourceName() == null ) {
            throwAtomikosSQLException("Property 'uniqueResourceName' cannot be null");
        }
        if ( getTestQuery() != null ) {
            LOGGER.logWarning(this + ": testQuery set - pool may be slower / you might want to consider setting maxLifetime instead...");
        }
        if ( getMinPoolSize() == DEFAULT_POOL_SIZE ) {
            LOGGER.logWarning ( this + ": poolSize equals default - this may cause performance problems!" );
        }
        
        try {
            //initialize JNDI infrastructure for lookup
            getReference();
            ConnectionFactory cf = doInit();
            connectionPool = new ConnectionPool(cf, this);
        
            
        
        } catch ( AtomikosSQLException e ) {
            //these are logged at creation time -> just rethrow
            throw e;
        } catch ( Exception ex) { 
            String msg =  "Cannot initialize AtomikosDataSourceBean";
            AtomikosSQLException.throwAtomikosSQLException ( msg , ex );
        }
        if ( LOGGER.isDebugEnabled() ) {
            LOGGER.logDebug ( this + ": init done." );
        }
    }
    
    public void close() 
    {
        if ( LOGGER.isInfoEnabled() ) {
            LOGGER.logInfo ( this + ": close..." );
        }
        if (connectionPool != null) {
            connectionPool.destroy();
        }
        connectionPool = null;
        doClose();
        try {
            IntraVmObjectRegistry.removeResource ( getUniqueResourceName() );
        } catch ( NameNotFoundException e ) {
            //ignore but log
            if ( LOGGER.isDebugEnabled() ) {
                LOGGER.logDebug ( this + ": Error removing from JNDI" , e );
            }
        }
        if ( LOGGER.isDebugEnabled() ) {
            LOGGER.logDebug ( this + ": close done." );
        }
    }
    
    protected abstract ConnectionFactory doInit() throws Exception;

    protected abstract void doClose();

    /* DataSource impl */

    public Connection getConnection ( HeuristicMessage msg ) throws SQLException 
    {
        if ( LOGGER.isInfoEnabled() ) {
            LOGGER.logInfo ( this + ": getConnection ( " + msg + " )..." );
        }
        Connection connection = null;
        long startTime = System.currentTimeMillis();
        init();
        long endTime = System.currentTimeMillis();
        log.info("getConnection run time(毫秒):"+(endTime - startTime));
        try {
            connection = (Connection) connectionPool.borrowConnection ( msg );
            
        } catch (CreateConnectionException ex) {
            throwAtomikosSQLException("Failed to grow the connection pool", ex);
        } catch (PoolExhaustedException e) {
            throwAtomikosSQLException ("Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.");
        } catch (ConnectionPoolException e) {
            throwAtomikosSQLException("Error borrowing connection", e );
        }
        if ( LOGGER.isDebugEnabled() ) {
            LOGGER.logDebug ( this + ": returning " + connection );
        }
        return connection;
    }

    public Connection getConnection(String username, String password) throws SQLException 
    {
        LOGGER.logWarning ( this + ": getConnection ( user , password ) ignores authentication - returning default connection" );
        return getConnection();
    }

    /**
     * Get the resource name. 
     */
    public String getUniqueResourceName() {
        return resourceName;
    }

    /**
     * Sets the resource name. Required.
     * 
     * @param resourceName An arbitrary user-specified value that identifies
     * this datasource. It must be unique for recovery purposes.
     */
    public void setUniqueResourceName(String resourceName) {
        this.resourceName = resourceName;
    }
    
    /**
     * Tests whether local transactions are allowed - defaults to true
     * for JDBC. This property is used by the pooling mechanism.
     */
    public boolean getLocalTransactionMode() {
        return true;
    }

    public Reference getReference() throws NamingException 
    {    
        return IntraVmObjectFactory.createReference ( this , getUniqueResourceName() );        
    }
    
    public Connection getConnection() throws SQLException
    {
        StringHeuristicMessage m = null;
        return getConnection ( m );
    }

    public Connection getConnection ( String msg ) throws SQLException
    {
        return getConnection ( new StringHeuristicMessage ( msg ) );
    }


    public Connection getConnection ( String user , String passwd , String msg )
            throws SQLException
    {
        LOGGER.logWarning ( this + ": getConnection ( user , password , msg ) ignores authentication - returning default connection" );
        return getConnection ( msg );
    }

  
    public Connection getConnection ( String user , String passwd ,
            HeuristicMessage msg ) throws SQLException
    {
        LOGGER.logWarning ( this + ": getConnection ( user , password , msg ) ignores authentication - returning default connection" );
        return getConnection ( msg );
    }

    /**
     * Sets the default isolation level of connections returned by this datasource.
     * Optional, defaults to the vendor-specific JDBC or DBMS settings.
     * 
     * @param defaultIsolationLevel The default isolation level. 
     * Negative values are ignored and result in vendor-specific JDBC driver or DBMS internal defaults.
     */
    public void setDefaultIsolationLevel(int defaultIsolationLevel) {
        this.defaultIsolationLevel = defaultIsolationLevel;
    }

    /**
     * Gets the default isolation level for connections created by this datasource. 
     * 
     * @return The default isolation level, or -1 if no specific value was set.
     * 
     */
    public int getDefaultIsolationLevel() {
        return defaultIsolationLevel;
    }
    
    public boolean isWrapperFor(Class<?> iface) {
        return isAssignableFromThisClass(iface) || isAssignableFromWrappedVendorClass(iface);
    }
    
    protected abstract boolean isAssignableFromWrappedVendorClass(Class<?> iface);

    private  boolean isAssignableFromThisClass(Class<?> iface) {
        return iface.isAssignableFrom(getClass());
    }

    public <T> T unwrap(Class<T> iface) throws SQLException {
        if (isAssignableFromThisClass(iface)) {
            return (T) this;
        } else if (isAssignableFromWrappedVendorClass(iface)) {
            return (T) unwrapVendorInstance();
        } 
        throw new SQLException("Not a wrapper for class: " + iface);
    }

    protected abstract Object unwrapVendorInstance();
    
    /**
     * JDK 1.7 requirement.
     * 
     * @throws SQLFeatureNotSupportedException
     */
    public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
        throw new SQLFeatureNotSupportedException();
    }

    /**
     * Refreshes all available connections in the pool.
     */
    public void refreshPool() {
        if (connectionPool != null) {
            connectionPool.refresh();
        }
    }

    public String getIsLoad() {
        return isLoad;
    }

    public void setIsLoad(String isLoad) {
        this.isLoad = isLoad;
    }
    
}

这是系统运行日志

2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- queryLine-service1:9771
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- AtomikosDataSoureBean '9771DB': getConnection ( null )...
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- [9771DB]数据源加载配置为[true],正常加载
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- AtomikosDataSoureBean '9771DB': init...
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.065 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: calling getAutoCommit...
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.065 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: calling prepareStatement(select Production_Line_Id as lineId ,Production_Line_Code as lineCode,Production_Line_Desc as lineDesc from pm_production_lines_t
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.450 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: close()...
2023-06-27 12:26:25,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:25.263 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- System run time(miao):69
2023-06-27 12:26:25,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:25.264 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO  c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- queryLine-service2:9771

第四行跟第五行之间时间间隔1分钟,不知道为什么会这样

共有1个答案

双恩
2023-06-28

建议通过aop的方式记录一下 (数据源名称 访问开始 访问结束 接口路径等信息), 后面分析看看是网络导致的访问变慢 还是 和访问量相关

 类似资料:
  • 本文向大家介绍CI配置多数据库访问的方法,包括了CI配置多数据库访问的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了CI配置多数据库访问的方法。分享给大家供大家参考,具体如下: 1、修改datebase.php文件,将: 修改成: 2、将原来的数据库链接定义复制一份,如当前 其他的都不需要修改,然后在你的控制器里面加载 构造函数: 使用方式: 更多关于CodeIgniter相关内容感

  • 问题内容: 我有一个需要配置基于Spring的应用程序以与两个数据库一起使用的要求。我们有两个数据库,一个用于保存实时数据,另一个数据库用作数据仓库,并包含存档的数据(其结构与实时数据库完全相同)。 为简单起见,假设存在搜索产品的请求。应用程序应该做的是在实时数据库中搜索产品详细信息,如果找不到,它将检查存档数据库。 如果需要配置这样的设置,是否仍需要配置数据源,搜索代码是否必须使用第一个数据源来

  • 在我的数据库中,某个表的许多记录需要我的java spring应用程序不时处理。该表的每一行都有一个布尔标志,表示当前是否正在处理给定的记录。 我所看到的是在不同的服务器上多次部署我的java spring应用程序,全部访问同一个共享数据库,用一些负载平衡器复制同一个应用程序,等等。 但是,一次只有一个 Java 应用程序实例可以处理该特定表的给定数据库记录。 有哪些不同的方法来加强这种约束? 我

  • 不同的程序设计语言会有各自不同的数据库访问接口,程序语言通过这些接口,执行 SQL 语句,进行数据库管理。主要的数据库访问接口主要有  ODBC、JDBC、ADO.NET 和 PDO。 ODBC ODBC(Open Database Connectivity,开放数据库互连)为访问不同的 SQL 数据库提供了一个共同的接口。ODBC 使用 SQL 作为访问数据的标准。这一接口提供了最大限度的互操作

  • ActiveX Data Objects (ADO) 是一项容易使用并且可扩展的将数据库访问添加到 Web 页的技术。可以使用 ADO 去编写紧凑简明的脚本以便连接到 Open Database Connectivity (ODBC) 兼容的数据库和 OLE DB 兼容的数据源。如果您是一个对数据库连接有一定了解的脚本编写人员,那么您将发现 ADO 命令语句并不复杂而且容易掌握。同样地,如果您是一

  • 对许多Web应用程序而言,数据库都是其核心所在。数据库几乎可以用来存储你想查询和修改的任何信息,比如用户信息、产品目录或者新闻列表等。 Go没有内置的驱动支持任何的数据库,但是Go定义了database/sql接口,用户可以基于驱动接口开发相应数据库的驱动,5.1小节里面介绍Go设计的一些驱动,介绍Go是如何设计数据库驱动接口的。5.2至5.4小节介绍目前使用的比较多的一些关系型数据驱动以及如何使