• TDDL实践


    使用入门-数据源配置

    • 数据源配置,tddl的入口,从datasource切入
    <bean id="tddlDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
        <property name="appName" value="tddl_sample" />
        <property name="dynamicRule" value="true"/> 
    </bean>
    • Sequence生成器
    <bean id="seqStudent" class="com.taobao.tddl.client.sequence.impl.GroupSequence" init-method="init">
    	<property name="sequenceDao" ref="idSequenceDao" />
    	<property name="name" value="seq_Student" />
    </bean>
    • 指定静态文件,3.0以后支持动态推送
    <bean id="myDataSource" class="com.taobao.tddl.client.jdbc.TDataSource" init-method="init">
        <property name="appName" value="tddl_sample"/>
        <property name="appRuleFile" value="classpath:tddl-rule.xml"/>
        <property name="useLocalConfig" value="true"/>
    </bean>

    myDataSource--分库分表数据源

    appName--数据库代号从dba获得

    appRuleFile--分库分表配置文件

    useLocalConfig--使用本地配置

    • Sequence配置:  tddl-sequence.xml
    <bean id="sequenceDao" class="com.taobao.tddl.client.sequence.impl.GroupSequenceDao" init-method="init">
        <!-- appName,必填 -->
        <property name="appName" value="CUNTAO_SUPPLIER_APP" />
        <!-- 数据源的个数 -->
        <property name="dscount" value="1" />
        <!-- dbGroupKeys 必填 -->
        <!-- 如果在末尾插入"-OFF",该源将被关掉,该源占据的SQL段会被保留" -->
        <!-- 当dbGroupKeys中配置的个数小于dbcount的值的时候,默认配置了"-OFF"的源 -->
        <property name="dbGroupKeys">
            <list>
                <value>CUNTAO_SUPPLIER_BODY00_GROUP</value>
            </list>
        </property>
        <!-- 内步长 ,默认为1000,取值在1-100000之间 -->
        <property name="innerStep" value="500" />
        <!-- 重试次数,在多个groupDataSource的场景下,建议设置成1-2次。默认为2次 -->
        <property name="retryTimes" value="2" />
        <!-- sequence表的表名 -->
        <property name="tableName" value="cuntao_supplier_sequence" />
        <!-- 自适应开关 ,默认为false -->
        <property name="adjust" value="true" />
    </bean>

    TDDL分库分表配置bean

    tddl-rule.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
        <bean id="vtabroot" class="com.taobao.tddl.interact.rule.VirtualTableRoot" init-method="init">
            <property name="defaultDbIndex" value="CUNTAO_SUPPLIER_GROUP"/>
            <property name="dbType" value="MYSQL"/>
            <property name="tableRules">
                <map>
                    <entry key="cuntao_purchase_order" value-ref="cuntao_purchase_order_bean"/>
                    <entry key="cuntao_sub_purchase_order" value-ref="cuntao_sub_purchase_order_bean"/>
                    <entry key="cuntao_logistics_order" value-ref="cuntao_logistics_order_bean"/>
                    <entry key="cuntao_sub_logistics_order" value-ref="cuntao_sub_logistics_order_bean"/>
                </map>
            </property>
        </bean>
        <bean id="cuntao_purchase_order_bean" class="com.taobao.tddl.interact.rule.TableRule">
            <property name="dbNamePattern" value="CUNTAO_SUPPLIER_BODY{00}_GROUP"/>
            <property name="dbRuleArray">
                <value>(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)</value>
            </property>
            <property name="tbNamePattern" value="cuntao_purchase_order_{0000}" />
            <property name="tbRuleArray">
                <value>#supplier_id,1,256#.longValue() % 10000 % 256</value>
            </property>
        </bean>
    </beans>
    

      

    配置项说明
    分表总配置VirtualTableRoot:
    其中,defaultDbIndex是appgroup,从DBA获取;dbType,数据库类型;tableRules引入各个表的配置

    分库分表配置TableRule;其中,dbNamePattern分库规则,大括号会替换成dbRuleArray中的值.
    dbRuleArray,分库计算方法,(#supplier_id,1,256#.longValue() % 10000 % 256).intdiv(32)表示以supplier_id为分表键,256张表,8个库所以除以32,我们计算规则取后四位计算所以先模10000.

    tbNamePattern分表规则,大括号会替换成tbRuleArray中的值。
    dbRuleArray,分表计算方法,#supplier_id,1,256#.longValue() % 10000 % 256 就是分库计算方法不除以32.

     

    sequence生成bean
    我们用的sequence是一个单库单表的数据库,即每次使用GroupSequence获取新的seq值来计算id,保证全局各个表不会发生id冲突。

    appName,从DBA获得。

    dbGroupKeys,所在库名称

    tableName,sequence表名,可以使用一个sequence表来计算多个表的id,因为每个表实际只占用一行数据。

    name,目标表在sequence表中的key,一般取表名,其实是任意的。

    • DefaultSequenceDao源码
    public class DefaultSequenceDao implements SequenceDao
    {
      private static final Log log = LogFactory.getLog(DefaultSequenceDao.class);
      private static final int MIN_STEP = 1;
      private static final int MAX_STEP = 100000;
      private static final int DEFAULT_STEP = 1000;
      private static final int DEFAULT_RETRY_TIMES = 150;
      private static final String DEFAULT_TABLE_NAME = "sequence";
      private static final String DEFAULT_NAME_COLUMN_NAME = "name";
      private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
      private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
      private static final long DELTA = 100000000L;
    private DataSource dataSource; private int retryTimes = 150; private int step = 1000; private String tableName = "sequence"; private String nameColumnName = "name"; private String valueColumnName = "value"; private String gmtModifiedColumnName = "gmt_modified"; private volatile String selectSql; private volatile String updateSql; public SequenceRange nextRange(String name) throws SequenceException { if (name == null) { throw new IllegalArgumentException("序列名称不能为空"); } Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; for (int i = 0; i < this.retryTimes + 1; i++) { long oldValue; long newValue; try { conn = this.dataSource.getConnection(); stmt = conn.prepareStatement(getSelectSql()); stmt.setString(1, name); rs = stmt.executeQuery(); rs.next(); oldValue = rs.getLong(1); if (oldValue < 0L) { StringBuilder message = new StringBuilder(); message.append("Sequence value cannot be less than zero, value = ").append(oldValue); message.append(", please check table ").append(getTableName()); throw new SequenceException(message.toString()); } if (oldValue > 9223372036754775807L) { StringBuilder message = new StringBuilder(); message.append("Sequence value overflow, value = ").append(oldValue); message.append(", please check table ").append(getTableName()); throw new SequenceException(message.toString()); } newValue = oldValue + getStep(); } catch (SQLException e) { throw new SequenceException(e); } finally { closeResultSet(rs); rs = null; closeStatement(stmt); stmt = null; closeConnection(conn); conn = null; } try { conn = this.dataSource.getConnection(); stmt = conn.prepareStatement(getUpdateSql()); stmt.setLong(1, newValue); stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis())); stmt.setString(3, name); stmt.setLong(4, oldValue); int affectedRows = stmt.executeUpdate(); if (affectedRows == 0) { closeStatement(stmt); stmt = null; closeConnection(conn); conn = null; } else { return new SequenceRange(oldValue + 1L, newValue); } } catch (SQLException e) { throw new SequenceException(e); } finally { closeStatement(stmt); stmt = null; closeConnection(conn); conn = null; } } throw new SequenceException("Retried too many times, retryTimes = " + this.retryTimes); } private String getSelectSql() { if (this.selectSql == null) { synchronized (this) { if (this.selectSql == null) { StringBuilder buffer = new StringBuilder(); buffer.append("select ").append(getValueColumnName()); buffer.append(" from ").append(getTableName()); buffer.append(" where ").append(getNameColumnName()).append(" = ?"); this.selectSql = buffer.toString(); } } } return this.selectSql; } private String getUpdateSql() { if (this.updateSql == null) { synchronized (this) { if (this.updateSql == null) { StringBuilder buffer = new StringBuilder(); buffer.append("update ").append(getTableName()); buffer.append(" set ").append(getValueColumnName()).append(" = ?, "); buffer.append(getGmtModifiedColumnName()).append(" = ? where "); buffer.append(getNameColumnName()).append(" = ? and "); buffer.append(getValueColumnName()).append(" = ?"); this.updateSql = buffer.toString(); } } } return this.updateSql; } private static void closeResultSet(ResultSet rs) { if (rs != null) try { rs.close(); } catch (SQLException e) { log.debug("Could not close JDBC ResultSet", e); } catch (Throwable e) { log.debug("Unexpected exception on closing JDBC ResultSet", e); } } private static void closeStatement(Statement stmt) { if (stmt != null) try { stmt.close(); } catch (SQLException e) { log.debug("Could not close JDBC Statement", e); } catch (Throwable e) { log.debug("Unexpected exception on closing JDBC Statement", e); } } private static void closeConnection(Connection conn) { if (conn != null) try { conn.close(); } catch (SQLException e) { log.debug("Could not close JDBC Connection", e); } catch (Throwable e) { log.debug("Unexpected exception on closing JDBC Connection", e); } } ...
    • GroupSequenceDao源码
    public class GroupSequenceDao implements SequenceDao
    {
      private static final Log log = LogFactory.getLog(GroupSequenceDao.class);
      private static final int MIN_STEP = 1;
      private static final int MAX_STEP = 100000;
      private static final int DEFAULT_INNER_STEP = 1000;
      private static final int DEFAULT_RETRY_TIMES = 2;
      private static final String DEFAULT_TABLE_NAME = "sequence";
      private static final String DEFAULT_NAME_COLUMN_NAME = "name";
      private static final String DEFAULT_VALUE_COLUMN_NAME = "value";
      private static final String DEFAULT_GMT_MODIFIED_COLUMN_NAME = "gmt_modified";
      private static final int DEFAULT_DSCOUNT = 2;
      private static final Boolean DEFAULT_ADJUST = Boolean.valueOf(false);
      private static final long DELTA = 100000000L;
      private String appName;
      private List<String> dbGroupKeys;
      private Map<String, DataSource> dataSourceMap;
      private boolean adjust = DEFAULT_ADJUST.booleanValue();
    
      private int retryTimes = 2;
      private int dscount = 2;
      private int innerStep = 1000;
      private int outStep = 1000;
      private String tableName = "sequence";
      private String nameColumnName = "name";
      private String valueColumnName = "value";
      private String gmtModifiedColumnName = "gmt_modified";
      private volatile String selectSql;
      private volatile String updateSql;
      private volatile String insertSql;
      private ConcurrentHashMap<Integer, AtomicInteger> excludedKeyCount = new ConcurrentHashMap(this.dscount);
      private int maxSkipCount = 10000;
      private boolean useSlowProtect = false;
      private int protectMilliseconds = 50;
      private ExecutorService exec = Executors.newFixedThreadPool(1);
    
      public void init()
        throws SequenceException
      {
        if (StringUtils.isEmpty(this.appName)) {
          SequenceException sequenceException = new SequenceException("appName is Null ");
    
          log.error("没有配置appName", sequenceException);
          throw sequenceException;
        }
        if ((this.dbGroupKeys == null) || (this.dbGroupKeys.size() == 0)) {
          log.error("没有配置dbgroupKeys");
          throw new SequenceException("dbgroupKeys为空!");
        }
    
        this.dataSourceMap = new HashMap();
        for (String dbGroupKey : this.dbGroupKeys)
          if (!dbGroupKey.toUpperCase().endsWith("-OFF"))
          {
            TGroupDataSource tGroupDataSource = new TGroupDataSource(dbGroupKey, this.appName);
    
            tGroupDataSource.init();
            this.dataSourceMap.put(dbGroupKey, tGroupDataSource);
          }
        if (this.dbGroupKeys.size() >= this.dscount)
          this.dscount = this.dbGroupKeys.size();
        else {
          for (int ii = this.dbGroupKeys.size(); ii < this.dscount; ii++) {
            this.dbGroupKeys.add(new StringBuilder().append(this.dscount).append("-OFF").toString());
          }
        }
        this.outStep = (this.innerStep * this.dscount);
    
        StringBuilder sb = new StringBuilder();
        sb.append("GroupSequenceDao初始化完成:
     ");
        sb.append("appName:").append(this.appName).append("
    ");
        sb.append("innerStep:").append(this.innerStep).append("
    ");
        sb.append("dataSource:").append(this.dscount).append("个:");
        for (String str : this.dbGroupKeys) {
          sb.append("[").append(str).append("]、");
        }
        sb.append("
    ");
        sb.append("adjust:").append(this.adjust).append("
    ");
        sb.append("retryTimes:").append(this.retryTimes).append("
    ");
        sb.append("tableName:").append(this.tableName).append("
    ");
        sb.append("nameColumnName:").append(this.nameColumnName).append("
    ");
        sb.append("valueColumnName:").append(this.valueColumnName).append("
    ");
        sb.append("gmtModifiedColumnName:").append(this.gmtModifiedColumnName).append("
    ");
    
        log.info(sb.toString());
      }
    
      private boolean check(int index, long value)
      {
        return value % this.outStep == index * this.innerStep;
      }
    
      public void adjust(String name)
        throws SequenceException, SQLException
      {
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
    
        for (int i = 0; i < this.dbGroupKeys.size(); i++)
          if (!((String)this.dbGroupKeys.get(i)).toUpperCase().endsWith("-OFF"))
          {
            TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(i));
            try
            {
              conn = tGroupDataSource.getConnection();
              stmt = conn.prepareStatement(getSelectSql());
              stmt.setString(1, name);
              GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
              rs = stmt.executeQuery();
              int item = 0;
              while (rs.next()) {
                item++;
                long val = rs.getLong(getValueColumnName());
                if (!check(i, val))
                {
                  if (isAdjust()) {
                    adjustUpdate(i, val, name);
                  } else {
                    log.error("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
                    throw new SequenceException("数据库中配置的初值出错!请调整你的数据库,或者启动adjust开关");
                  }
                }
              }
    
              if (item == 0)
              {
                if (isAdjust()) {
                  adjustInsert(i, name);
                } else {
                  log.error("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
                  throw new SequenceException("数据库中未配置该sequence!请往数据库中插入sequence记录,或者启动adjust开关");
                }
              }
            }
            catch (SQLException e) {
              log.error("初值校验和自适应过程中出错.", e);
              throw e;
            } finally {
              closeResultSet(rs);
              rs = null;
              closeStatement(stmt);
              stmt = null;
              closeConnection(conn);
              conn = null;
            }
          }
      }
    
      private void adjustUpdate(int index, long value, String name)
        throws SequenceException, SQLException
      {
        long newValue = value - value % this.outStep + this.outStep + index * this.innerStep;
        TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
    
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
          conn = tGroupDataSource.getConnection();
          stmt = conn.prepareStatement(getUpdateSql());
          stmt.setLong(1, newValue);
          stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
          stmt.setString(3, name);
          stmt.setLong(4, value);
          GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
          int affectedRows = stmt.executeUpdate();
          if (affectedRows == 0) {
            throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at  ").append(name).append(" update affectedRow =0").toString());
          }
    
          log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append("更新初值成功!").append("sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString());
        }
        catch (SQLException e) {
          log.error(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e);
    
          throw new SequenceException(new StringBuilder().append("由于SQLException,更新初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("更新过程:").append(value).append("-->").append(newValue).toString(), e);
        }
        finally
        {
          closeStatement(stmt);
          stmt = null;
          closeConnection(conn);
          conn = null;
        }
      }
    
      private void adjustInsert(int index, String name)
        throws SequenceException, SQLException
      {
        TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
    
        long newValue = index * this.innerStep;
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
          conn = tGroupDataSource.getConnection();
          stmt = conn.prepareStatement(getInsertSql());
          stmt.setString(1, name);
          stmt.setLong(2, newValue);
          stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
          GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
          int affectedRows = stmt.executeUpdate();
          if (affectedRows == 0) {
            throw new SequenceException(new StringBuilder().append("faild to auto adjust init value at  ").append(name).append(" update affectedRow =0").toString());
          }
    
          log.info(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append("   name:").append(name).append("插入初值:").append(name).append("value:").append(newValue).toString());
        }
        catch (SQLException e)
        {
          log.error(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("   value:").append(newValue).toString(), e);
    
          throw new SequenceException(new StringBuilder().append("由于SQLException,插入初值自适应失败!dbGroupIndex:").append((String)this.dbGroupKeys.get(index)).append(",sequence Name:").append(name).append("   value:").append(newValue).toString(), e);
        }
        finally
        {
          closeResultSet(rs);
          rs = null;
          closeStatement(stmt);
          stmt = null;
          closeConnection(conn);
          conn = null;
        }
      }
    
      public SequenceRange nextRange(final String name)
        throws SequenceException
      {
        if (name == null) {
          log.error("序列名为空!");
          throw new IllegalArgumentException("序列名称不能为空");
        }
    
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
    
        int[] randomIntSequence = RandomSequence.randomIntSequence(this.dscount);
        for (int i = 0; i < this.retryTimes; i++) {
          for (int j = 0; j < this.dscount; j++) {
            boolean readSuccess = false;
            boolean writeSuccess = false;
            int index = randomIntSequence[j];
            if (!((String)this.dbGroupKeys.get(index)).toUpperCase().endsWith("-OFF"))
            {
              if (this.excludedKeyCount.get(Integer.valueOf(index)) != null) {
                if (((AtomicInteger)this.excludedKeyCount.get(Integer.valueOf(index))).incrementAndGet() > this.maxSkipCount) {
                  this.excludedKeyCount.remove(Integer.valueOf(index));
                  log.error(new StringBuilder().append(this.maxSkipCount).append("次数已过,index为").append(index).append("的数据源后续重新尝试取序列").toString());
                }
    
              }
              else
              {
                final TGroupDataSource tGroupDataSource = (TGroupDataSource)this.dataSourceMap.get(this.dbGroupKeys.get(index));
                long oldValue;
                long newValue;
                try
                {
                  long oldValue;
                  if ((!this.useSlowProtect) || (this.excludedKeyCount.size() >= this.dscount - 1)) {
                    conn = tGroupDataSource.getConnection();
                    stmt = conn.prepareStatement(getSelectSql());
                    stmt.setString(1, name);
                    GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
                    rs = stmt.executeQuery();
                    rs.next();
                    oldValue = rs.getLong(1);
                  } else {
                    FutureTask future = new FutureTask(new Callable()
                    {
                      public Long call() throws Exception
                      {
                        Connection fconn = null;
                        PreparedStatement fstmt = null;
                        ResultSet frs = null;
                        try {
                          fconn = tGroupDataSource.getConnection();
                          fstmt = fconn.prepareStatement(GroupSequenceDao.this.getSelectSql());
                          fstmt.setString(1, name);
                          GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
                          frs = fstmt.executeQuery();
                          frs.next();
                          return Long.valueOf(frs.getLong(1));
                        } finally {
                          GroupSequenceDao.closeResultSet(frs);
                          frs = null;
                          GroupSequenceDao.closeStatement(fstmt);
                          fstmt = null;
                          GroupSequenceDao.closeConnection(fconn);
                          fconn = null;
                        }
                      }
                    });
                    try
                    {
                      this.exec.submit(future);
                      oldValue = ((Long)future.get(this.protectMilliseconds, TimeUnit.MILLISECONDS)).longValue();
                    } catch (InterruptedException e) {
                      throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:InterruptedException", e);
                    } catch (ExecutionException e) {
                      throw new SQLException("[SEQUENCE SLOW-PROTECTED MODE]:ExecutionException", e);
                    } catch (TimeoutException e) {
                      throw new SQLException(new StringBuilder().append("[SEQUENCE SLOW-PROTECTED MODE]:TimeoutException,当前设置超时时间为").append(this.protectMilliseconds).toString(), e);
                    }
                  }
    
                  if (oldValue < 0L) {
                    StringBuilder message = new StringBuilder();
                    message.append("Sequence value cannot be less than zero, value = ").append(oldValue);
    
                    message.append(", please check table ").append(getTableName());
    
                    log.info(message);
    
                    closeResultSet(rs);
                    rs = null;
                    closeStatement(stmt);
                    stmt = null;
                    closeConnection(conn);
                    conn = null; continue;
                  }
                  if (oldValue > 9223372036754775807L) {
                    StringBuilder message = new StringBuilder();
                    message.append("Sequence value overflow, value = ").append(oldValue);
    
                    message.append(", please check table ").append(getTableName());
    
                    log.info(message);
    
                    closeResultSet(rs);
                    rs = null;
                    closeStatement(stmt);
                    stmt = null;
                    closeConnection(conn);
                    conn = null; continue;
                  }
                  newValue = oldValue + this.outStep;
                  if (!check(index, newValue))
                  {
                    if (isAdjust()) {
                      newValue = newValue - newValue % this.outStep + this.outStep + index * this.innerStep;
                    }
                    else {
                      SequenceException sequenceException = new SequenceException(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString());
    
                      log.error(new StringBuilder().append((String)this.dbGroupKeys.get(index)).append(":").append(name).append("的值得错误,覆盖到其他范围段了!请修改数据库,或者开启adjust开关!").toString(), sequenceException);
    
                      throw sequenceException;
                    }
    
                  }
    
                  closeResultSet(rs);
                  rs = null;
                  closeStatement(stmt);
                  stmt = null;
                  closeConnection(conn);
                  conn = null;
                }
                catch (SQLException e)
                {
                  log.error(new StringBuilder().append("取范围过程中--查询出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e);
    
                  if (this.excludedKeyCount.size() < this.dscount - 1) {
                    this.excludedKeyCount.put(Integer.valueOf(index), new AtomicInteger(0));
                    log.error(new StringBuilder().append("暂时踢除index为").append(index).append("的数据源,").append(this.maxSkipCount).append("次后重新尝试").toString());
                  }
                }
                finally
                {
                  closeResultSet(rs);
                  rs = null;
                  closeStatement(stmt);
                  stmt = null;
                  closeConnection(conn);
                  conn = null;
                }
    
                try
                {
                  conn = tGroupDataSource.getConnection();
                  stmt = conn.prepareStatement(getUpdateSql());
                  stmt.setLong(1, newValue);
                  stmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
    
                  stmt.setString(3, name);
                  stmt.setLong(4, oldValue);
                  GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0);
                  int affectedRows = stmt.executeUpdate();
                  if (affectedRows == 0)
                  {
                    closeStatement(stmt);
                    stmt = null;
                    closeConnection(conn);
                    conn = null;
                  }
                  else
                  {
                    closeStatement(stmt);
                    stmt = null;
                    closeConnection(conn);
                    conn = null;
                  }
                }
                catch (SQLException e)
                {
                  log.error(new StringBuilder().append("取范围过程中--更新出错!").append((String)this.dbGroupKeys.get(index)).append(":").append(name).toString(), e);
                }
                finally
                {
                  closeStatement(stmt);
                  stmt = null;
                  closeConnection(conn);
                  conn = null;
                }
              }
            }
    
          }
    
          if (i == this.retryTimes - 2) {
            this.excludedKeyCount.clear();
          }
        }
        log.error(new StringBuilder().append("所有数据源都不可用!且重试").append(this.retryTimes).append("次后,仍然失败!").toString());
        throw new SequenceException("All dataSource faild to get value!");
      }
    
      private String getInsertSql() {
        if (this.insertSql == null) {
          synchronized (this) {
            if (this.insertSql == null) {
              StringBuilder buffer = new StringBuilder();
              buffer.append("insert into ").append(getTableName()).append("(");
    
              buffer.append(getNameColumnName()).append(",");
              buffer.append(getValueColumnName()).append(",");
              buffer.append(getGmtModifiedColumnName()).append(") values(?,?,?);");
    
              this.insertSql = buffer.toString();
            }
          }
        }
        return this.insertSql;
      }
    
      private String getSelectSql() {
        if (this.selectSql == null) {
          synchronized (this) {
            if (this.selectSql == null) {
              StringBuilder buffer = new StringBuilder();
              buffer.append("select ").append(getValueColumnName());
              buffer.append(" from ").append(getTableName());
              buffer.append(" where ").append(getNameColumnName()).append(" = ?");
    
              this.selectSql = buffer.toString();
            }
          }
        }
    
        return this.selectSql;
      }
    
      private String getUpdateSql() {
        if (this.updateSql == null) {
          synchronized (this) {
            if (this.updateSql == null) {
              StringBuilder buffer = new StringBuilder();
              buffer.append("update ").append(getTableName());
              buffer.append(" set ").append(getValueColumnName()).append(" = ?, ");
    
              buffer.append(getGmtModifiedColumnName()).append(" = ? where ");
    
              buffer.append(getNameColumnName()).append(" = ? and ");
              buffer.append(getValueColumnName()).append(" = ?");
    
              this.updateSql = buffer.toString();
            }
          }
        }
    
        return this.updateSql;
      }
    
      private static void closeResultSet(ResultSet rs) {
        if (rs != null)
          try {
            rs.close();
          } catch (SQLException e) {
            log.debug("Could not close JDBC ResultSet", e);
          } catch (Throwable e) {
            log.debug("Unexpected exception on closing JDBC ResultSet", e);
          }
      }
    
      private static void closeStatement(Statement stmt)
      {
        if (stmt != null)
          try {
            stmt.close();
          } catch (SQLException e) {
            log.debug("Could not close JDBC Statement", e);
          } catch (Throwable e) {
            log.debug("Unexpected exception on closing JDBC Statement", e);
          }
      }
    
      private static void closeConnection(Connection conn)
      {
        if (conn != null)
          try {
            conn.close();
          } catch (SQLException e) {
            log.debug("Could not close JDBC Connection", e);
          } catch (Throwable e) {
            log.debug("Unexpected exception on closing JDBC Connection", e);
          }
      }
     
  • 相关阅读:
    Max关闭WPF
    InstallShield安装过程介绍
    InstallShield相关资料整理
    .net reflection的一点研究
    (转)VMware增加磁盘容量方法
    领域驱动设计《读书笔记》
    《领域驱动设计C#2008实现》读书笔记
    深入研究c++对象模型
    <转载>com之包容聚合
    基于插件开发的架构研究
  • 原文地址:https://www.cnblogs.com/kaleidoscope/p/9779481.html
Copyright © 2020-2023  润新知