Search in sources :

Example 76 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat-Server by MyCATApache.

the class ConfigComparer method loadMigratorTables.

/*
	 * 加载迁移表信息,tables大小为0表示迁移schema下所有表
	 */
private void loadMigratorTables(String schemaName, String[] tables) {
    if (!DataMigratorUtil.isKeyExistIgnoreCase(oldSchemas, schemaName)) {
        throw new ConfigException("oldSchema:" + schemaName + " is not exists!");
    }
    if (!DataMigratorUtil.isKeyExistIgnoreCase(newSchemas, schemaName)) {
        throw new ConfigException("newSchema:" + schemaName + " is not exists!");
    }
    Map<String, TableConfig> oldTables = DataMigratorUtil.getValueIgnoreCase(oldSchemas, schemaName).getTables();
    Map<String, TableConfig> newTables = DataMigratorUtil.getValueIgnoreCase(newSchemas, schemaName).getTables();
    if (tables.length > 0) {
        // 指定schema下的表进行迁移
        for (int i = 0; i < tables.length; i++) {
            TableConfig oldTable = DataMigratorUtil.getValueIgnoreCase(oldTables, tables[i]);
            TableConfig newTable = DataMigratorUtil.getValueIgnoreCase(newTables, tables[i]);
            loadMigratorTable(oldTable, newTable, schemaName, tables[i]);
        }
    } else {
        // 迁移schema下所有的表
        // 校验新旧schema中的table配置是否一致
        Set<String> oldSet = oldTables.keySet();
        Set<String> newSet = newTables.keySet();
        if (!oldSet.equals(newSet)) {
            throw new ConfigException("new & old table config is not equal!");
        }
        for (String tableName : oldSet) {
            TableConfig oldTable = oldTables.get(tableName);
            TableConfig newTable = newTables.get(tableName);
            loadMigratorTable(oldTable, newTable, schemaName, tableName);
        }
    }
}
Also used : TableConfig(io.mycat.config.model.TableConfig) ConfigException(io.mycat.config.util.ConfigException)

Example 77 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat-Server by MyCATApache.

the class MycatServer method performXARecoveryLog.

// XA recovery log check
private void performXARecoveryLog() {
    // fetch the recovery log
    CoordinatorLogEntry[] coordinatorLogEntries = getCoordinatorLogEntries();
    for (int i = 0; i < coordinatorLogEntries.length; i++) {
        CoordinatorLogEntry coordinatorLogEntry = coordinatorLogEntries[i];
        boolean needRollback = false;
        for (int j = 0; j < coordinatorLogEntry.participants.length; j++) {
            ParticipantLogEntry participantLogEntry = coordinatorLogEntry.participants[j];
            if (participantLogEntry.txState == TxState.TX_PREPARED_STATE) {
                needRollback = true;
                break;
            }
        }
        if (needRollback) {
            for (int j = 0; j < coordinatorLogEntry.participants.length; j++) {
                ParticipantLogEntry participantLogEntry = coordinatorLogEntry.participants[j];
                // XA rollback
                String xacmd = "XA ROLLBACK " + coordinatorLogEntry.id + ';';
                OneRawSQLQueryResultHandler resultHandler = new OneRawSQLQueryResultHandler(new String[0], new XARollbackCallback());
                outloop: for (SchemaConfig schema : MycatServer.getInstance().getConfig().getSchemas().values()) {
                    for (TableConfig table : schema.getTables().values()) {
                        for (String dataNode : table.getDataNodes()) {
                            PhysicalDBNode dn = MycatServer.getInstance().getConfig().getDataNodes().get(dataNode);
                            if (dn.getDbPool().getSource().getConfig().getIp().equals(participantLogEntry.uri) && dn.getDatabase().equals(participantLogEntry.resourceName)) {
                                // XA STATE ROLLBACK
                                participantLogEntry.txState = TxState.TX_ROLLBACKED_STATE;
                                SQLJob sqlJob = new SQLJob(xacmd, dn.getDatabase(), resultHandler, dn.getDbPool().getSource());
                                sqlJob.run();
                                LOGGER.debug(String.format("[XA ROLLBACK] [%s] Host:[%s] schema:[%s]", xacmd, dn.getName(), dn.getDatabase()));
                                break outloop;
                            }
                        }
                    }
                }
            }
        }
    }
    // init into in memory cached
    for (int i = 0; i < coordinatorLogEntries.length; i++) {
        MultiNodeCoordinator.inMemoryRepository.put(coordinatorLogEntries[i].id, coordinatorLogEntries[i]);
    }
    // discard the recovery log
    MultiNodeCoordinator.fileRepository.writeCheckpoint(MultiNodeCoordinator.inMemoryRepository.getAllCoordinatorLogEntries());
}
Also used : OneRawSQLQueryResultHandler(io.mycat.sqlengine.OneRawSQLQueryResultHandler) PhysicalDBNode(io.mycat.backend.datasource.PhysicalDBNode) SchemaConfig(io.mycat.config.model.SchemaConfig) ParticipantLogEntry(io.mycat.backend.mysql.xa.ParticipantLogEntry) SQLJob(io.mycat.sqlengine.SQLJob) XARollbackCallback(io.mycat.backend.mysql.xa.XARollbackCallback) TableConfig(io.mycat.config.model.TableConfig) CoordinatorLogEntry(io.mycat.backend.mysql.xa.CoordinatorLogEntry)

Example 78 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat-Server by MyCATApache.

the class RouterUtil method changeCreateTable.

private static String changeCreateTable(SchemaConfig schema, String tableName, String sql) {
    if (schema.getTables().containsKey(tableName)) {
        MySqlStatementParser parser = new MySqlStatementParser(sql);
        SQLStatement insertStatement = parser.parseStatement();
        if (insertStatement instanceof MySqlCreateTableStatement) {
            TableConfig tableConfig = schema.getTables().get(tableName);
            AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
            if (algorithm instanceof SlotFunction) {
                SQLColumnDefinition column = new SQLColumnDefinition();
                column.setDataType(new SQLCharacterDataType("int"));
                column.setName(new SQLIdentifierExpr("_slot"));
                column.setComment(new SQLCharExpr("自动迁移算法slot,禁止修改"));
                ((SQLCreateTableStatement) insertStatement).getTableElementList().add(column);
                return insertStatement.toString();
            }
        }
    }
    return sql;
}
Also used : AbstractPartitionAlgorithm(io.mycat.route.function.AbstractPartitionAlgorithm) SQLCharExpr(com.alibaba.druid.sql.ast.expr.SQLCharExpr) SQLCharacterDataType(com.alibaba.druid.sql.ast.statement.SQLCharacterDataType) TableConfig(io.mycat.config.model.TableConfig) SQLIdentifierExpr(com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr) MySqlStatementParser(com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) MySqlCreateTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement) SQLColumnDefinition(com.alibaba.druid.sql.ast.statement.SQLColumnDefinition) SlotFunction(io.mycat.route.function.SlotFunction)

Example 79 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat-Server by MyCATApache.

the class RouterUtil method tryRouteForOneTable.

/**
 * 单表路由
 */
public static RouteResultset tryRouteForOneTable(SchemaConfig schema, DruidShardingParseInfo ctx, RouteCalculateUnit routeUnit, String tableName, RouteResultset rrs, boolean isSelect, LayerCachePool cachePool) throws SQLNonTransientException {
    if (isNoSharding(schema, tableName)) {
        return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql());
    }
    TableConfig tc = schema.getTables().get(tableName);
    if (tc == null) {
        String msg = "can't find table define in schema " + tableName + " schema:" + schema.getName();
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
    if (tc.isDistTable()) {
        return routeToDistTableNode(tableName, schema, rrs, ctx.getSql(), routeUnit.getTablesAndConditions(), cachePool, isSelect);
    }
    if (tc.isGlobalTable()) {
        // 全局表
        if (isSelect) {
            // global select ,not cache route result
            rrs.setCacheAble(false);
            return routeToSingleNode(rrs, getAliveRandomDataNode(tc), /*getRandomDataNode(tc)*/
            ctx.getSql());
        } else {
            // insert into 全局表的记录
            return routeToMultiNode(false, rrs, tc.getDataNodes(), ctx.getSql(), true);
        }
    } else {
        // 单表或者分库表
        if (!checkRuleRequired(schema, ctx, routeUnit, tc)) {
            throw new IllegalArgumentException("route rule for table " + tc.getName() + " is required: " + ctx.getSql());
        }
        if (tc.getPartitionColumn() == null && !tc.isSecondLevel()) {
            // return RouterUtil.routeToSingleNode(rrs, tc.getDataNodes().get(0),ctx.getSql());
            return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());
        } else {
            // 每个表对应的路由映射
            Map<String, Set<String>> tablesRouteMap = new HashMap<String, Set<String>>();
            if (routeUnit.getTablesAndConditions() != null && routeUnit.getTablesAndConditions().size() > 0) {
                RouterUtil.findRouteWithcConditionsForTables(schema, rrs, routeUnit.getTablesAndConditions(), tablesRouteMap, ctx.getSql(), cachePool, isSelect);
                if (rrs.isFinishedRoute()) {
                    return rrs;
                }
            }
            if (tablesRouteMap.get(tableName) == null) {
                return routeToMultiNode(rrs.isCacheAble(), rrs, tc.getDataNodes(), ctx.getSql());
            } else {
                return routeToMultiNode(rrs.isCacheAble(), rrs, tablesRouteMap.get(tableName), ctx.getSql());
            }
        }
    }
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) TableConfig(io.mycat.config.model.TableConfig)

Example 80 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat-Server by MyCATApache.

the class RouterUtil method tryRouteForTables.

/**
 * 多表路由
 */
public static RouteResultset tryRouteForTables(SchemaConfig schema, DruidShardingParseInfo ctx, RouteCalculateUnit routeUnit, RouteResultset rrs, boolean isSelect, LayerCachePool cachePool) throws SQLNonTransientException {
    List<String> tables = ctx.getTables();
    if (schema.isNoSharding() || (tables.size() >= 1 && isNoSharding(schema, tables.get(0)))) {
        return routeToSingleNode(rrs, schema.getDataNode(), ctx.getSql());
    }
    // 只有一个表的
    if (tables.size() == 1) {
        return RouterUtil.tryRouteForOneTable(schema, ctx, routeUnit, tables.get(0), rrs, isSelect, cachePool);
    }
    Set<String> retNodesSet = new HashSet<String>();
    // 每个表对应的路由映射
    Map<String, Set<String>> tablesRouteMap = new HashMap<String, Set<String>>();
    // 分库解析信息不为空
    Map<String, Map<String, Set<ColumnRoutePair>>> tablesAndConditions = routeUnit.getTablesAndConditions();
    if (tablesAndConditions != null && tablesAndConditions.size() > 0) {
        // 为分库表找路由
        RouterUtil.findRouteWithcConditionsForTables(schema, rrs, tablesAndConditions, tablesRouteMap, ctx.getSql(), cachePool, isSelect);
        if (rrs.isFinishedRoute()) {
            return rrs;
        }
    }
    // 为全局表和单库表找路由
    for (String tableName : tables) {
        TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
        if (tableConfig == null) {
            // add 如果表读取不到则先将表名从别名中读取转化后再读取
            String alias = ctx.getTableAliasMap().get(tableName);
            if (!StringUtil.isEmpty(alias)) {
                tableConfig = schema.getTables().get(alias.toUpperCase());
            }
            if (tableConfig == null) {
                String msg = "can't find table define in schema " + tableName + " schema:" + schema.getName();
                LOGGER.warn(msg);
                throw new SQLNonTransientException(msg);
            }
        }
        if (tableConfig.isGlobalTable()) {
            // 全局表
            if (tablesRouteMap.get(tableName) == null) {
                tablesRouteMap.put(tableName, new HashSet<String>());
            }
            tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
        } else if (tablesRouteMap.get(tableName) == null) {
            // 余下的表都是单库表
            tablesRouteMap.put(tableName, new HashSet<String>());
            tablesRouteMap.get(tableName).addAll(tableConfig.getDataNodes());
        }
    }
    boolean isFirstAdd = true;
    for (Map.Entry<String, Set<String>> entry : tablesRouteMap.entrySet()) {
        if (entry.getValue() == null || entry.getValue().size() == 0) {
            throw new SQLNonTransientException("parent key can't find any valid datanode ");
        } else {
            if (isFirstAdd) {
                retNodesSet.addAll(entry.getValue());
                isFirstAdd = false;
            } else {
                retNodesSet.retainAll(entry.getValue());
                if (retNodesSet.size() == 0) {
                    // 两个表的路由无交集
                    String errMsg = "invalid route in sql, multi tables found but datanode has no intersection " + " sql:" + ctx.getSql();
                    LOGGER.warn(errMsg);
                    throw new SQLNonTransientException(errMsg);
                }
            }
        }
    }
    if (retNodesSet != null && retNodesSet.size() > 0) {
        String tableName = tables.get(0);
        TableConfig tableConfig = schema.getTables().get(tableName.toUpperCase());
        if (tableConfig.isDistTable()) {
            routeToDistTableNode(tableName, schema, rrs, ctx.getSql(), tablesAndConditions, cachePool, isSelect);
            return rrs;
        }
        if (retNodesSet.size() > 1 && isAllGlobalTable(ctx, schema)) {
            // mulit routes ,not cache route result
            if (isSelect) {
                rrs.setCacheAble(false);
                routeToSingleNode(rrs, retNodesSet.iterator().next(), ctx.getSql());
            } else {
                // delete 删除全局表的记录
                routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql(), true);
            }
        } else {
            routeToMultiNode(isSelect, rrs, retNodesSet, ctx.getSql());
        }
    }
    return rrs;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) ColumnRoutePair(io.mycat.sqlengine.mpp.ColumnRoutePair) SQLNonTransientException(java.sql.SQLNonTransientException) TableConfig(io.mycat.config.model.TableConfig) Map(java.util.Map) HashMap(java.util.HashMap) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Aggregations

TableConfig (io.mycat.config.model.TableConfig)84 SchemaConfig (io.mycat.config.model.SchemaConfig)26 SQLNonTransientException (java.sql.SQLNonTransientException)26 Test (org.junit.Test)18 RuleConfig (io.mycat.config.model.rule.RuleConfig)16 RouteResultset (io.mycat.route.RouteResultset)14 AbstractPartitionAlgorithm (io.mycat.route.function.AbstractPartitionAlgorithm)14 HashMap (java.util.HashMap)14 MySqlStatementParser (com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser)12 SlotFunction (io.mycat.route.function.SlotFunction)12 ArrayList (java.util.ArrayList)12 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)10 MySqlInsertStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)8 PhysicalDBNode (io.mycat.backend.datasource.PhysicalDBNode)8 ConfigException (io.mycat.config.util.ConfigException)8 RouteResultsetNode (io.mycat.route.RouteResultsetNode)8 HashSet (java.util.HashSet)8 SQLCharExpr (com.alibaba.druid.sql.ast.expr.SQLCharExpr)6 SQLIdentifierExpr (com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr)6 CacheService (io.mycat.cache.CacheService)6