Search in sources :

Example 21 with TableConfig

use of io.mycat.config.model.TableConfig in project Mycat_plus by coderczp.

the class GlobalTableUtil method consistencyCheck.

public static void consistencyCheck() {
    MycatConfig config = MycatServer.getInstance().getConfig();
    for (String key : globalTableMap.keySet()) {
        TableConfig table = globalTableMap.get(key);
        // <table name="travelrecord" dataNode="dn1,dn2,dn3"
        List<String> dataNodeList = table.getDataNodes();
        // 记录本次已经执行的datanode
        // 多个 datanode 对应到同一个 PhysicalDatasource 只执行一次
        Map<String, String> executedMap = new HashMap<>();
        for (String nodeName : dataNodeList) {
            Map<String, PhysicalDBNode> map = config.getDataNodes();
            for (String k2 : map.keySet()) {
                // <dataNode name="dn1" dataHost="localhost1" database="db1" />
                PhysicalDBNode dBnode = map.get(k2);
                if (nodeName.equals(dBnode.getName())) {
                    // dn1,dn2,dn3
                    PhysicalDBPool pool = dBnode.getDbPool();
                    Collection<PhysicalDatasource> allDS = pool.genAllDataSources();
                    for (PhysicalDatasource pds : allDS) {
                        if (pds instanceof MySQLDataSource) {
                            MySQLDataSource mds = (MySQLDataSource) pds;
                            if (executedMap.get(pds.getName()) == null) {
                                MySQLConsistencyChecker checker = new MySQLConsistencyChecker(mds, table.getName());
                                isInnerColumnCheckFinished = 0;
                                checker.checkInnerColumnExist();
                                while (isInnerColumnCheckFinished <= 0) {
                                    LOGGER.debug("isInnerColumnCheckFinished:" + isInnerColumnCheckFinished);
                                    try {
                                        TimeUnit.SECONDS.sleep(1);
                                    } catch (InterruptedException e) {
                                        LOGGER.warn(e.getMessage());
                                    }
                                }
                                LOGGER.debug("isInnerColumnCheckFinished:" + isInnerColumnCheckFinished);
                                // 一种 check 完成之后,再进行另一种 check
                                checker = new MySQLConsistencyChecker(mds, table.getName());
                                isColumnCountCheckFinished = 0;
                                checker.checkRecordCout();
                                while (isColumnCountCheckFinished <= 0) {
                                    LOGGER.debug("isColumnCountCheckFinished:" + isColumnCountCheckFinished);
                                    try {
                                        TimeUnit.SECONDS.sleep(1);
                                    } catch (InterruptedException e) {
                                        LOGGER.warn(e.getMessage());
                                    }
                                }
                                LOGGER.debug("isColumnCountCheckFinished:" + isColumnCountCheckFinished);
                                checker = new MySQLConsistencyChecker(mds, table.getName());
                                checker.checkMaxTimeStamp();
                                executedMap.put(pds.getName(), nodeName);
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : PhysicalDBNode(io.mycat.backend.datasource.PhysicalDBNode) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) PhysicalDBPool(io.mycat.backend.datasource.PhysicalDBPool) MycatConfig(io.mycat.config.MycatConfig) MySQLConsistencyChecker(io.mycat.backend.heartbeat.MySQLConsistencyChecker) PhysicalDatasource(io.mycat.backend.datasource.PhysicalDatasource) MySQLDataSource(io.mycat.backend.mysql.nio.MySQLDataSource) TableConfig(io.mycat.config.model.TableConfig)

Example 22 with TableConfig

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

the class XMLSchemaLoader method processChildTables.

private void processChildTables(Map<String, TableConfig> tables, TableConfig parentTable, String dataNodes, Element tableNode) {
    // parse child tables
    NodeList childNodeList = tableNode.getChildNodes();
    for (int j = 0; j < childNodeList.getLength(); j++) {
        Node theNode = childNodeList.item(j);
        if (!theNode.getNodeName().equals("childTable")) {
            continue;
        }
        Element childTbElement = (Element) theNode;
        // 读取子表信息
        String cdTbName = childTbElement.getAttribute("name").toUpperCase();
        String primaryKey = childTbElement.hasAttribute("primaryKey") ? childTbElement.getAttribute("primaryKey").toUpperCase() : null;
        boolean autoIncrement = false;
        if (childTbElement.hasAttribute("autoIncrement")) {
            autoIncrement = Boolean.parseBoolean(childTbElement.getAttribute("autoIncrement"));
        }
        boolean needAddLimit = true;
        if (childTbElement.hasAttribute("needAddLimit")) {
            needAddLimit = Boolean.parseBoolean(childTbElement.getAttribute("needAddLimit"));
        }
        String subTables = childTbElement.getAttribute("subTables");
        // 子表join键,和对应的parent的键,父子表通过这个关联
        String joinKey = childTbElement.getAttribute("joinKey").toUpperCase();
        String parentKey = childTbElement.getAttribute("parentKey").toUpperCase();
        TableConfig table = new TableConfig(cdTbName, primaryKey, autoIncrement, needAddLimit, TableConfig.TYPE_GLOBAL_DEFAULT, dataNodes, getDbType(dataNodes), null, false, parentTable, true, joinKey, parentKey, subTables);
        if (tables.containsKey(table.getName())) {
            throw new ConfigException("table " + table.getName() + " duplicated!");
        }
        tables.put(table.getName(), table);
        // 对于子表的子表,递归处理
        processChildTables(tables, table, dataNodes, childTbElement);
    }
}
Also used : NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) TableConfig(io.mycat.config.model.TableConfig) ConfigException(io.mycat.config.util.ConfigException)

Example 23 with TableConfig

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

the class XMLSchemaLoader method loadTables.

private Map<String, TableConfig> loadTables(Element node) {
    // Map<String, TableConfig> tables = new HashMap<String, TableConfig>();
    // 支持表名中包含引号[`] BEN GONG
    Map<String, TableConfig> tables = new TableConfigMap();
    NodeList nodeList = node.getElementsByTagName("table");
    for (int i = 0; i < nodeList.getLength(); i++) {
        Element tableElement = (Element) nodeList.item(i);
        String tableNameElement = tableElement.getAttribute("name").toUpperCase();
        // TODO:路由, 增加对动态日期表的支持
        String tableNameSuffixElement = tableElement.getAttribute("nameSuffix").toUpperCase();
        if (!"".equals(tableNameSuffixElement)) {
            if (tableNameElement.split(",").length > 1) {
                throw new ConfigException("nameSuffix " + tableNameSuffixElement + ", require name parameter cannot multiple breaks!");
            }
            // 前缀用来标明日期格式
            tableNameElement = doTableNameSuffix(tableNameElement, tableNameSuffixElement);
        }
        // 记录主键,用于之后路由分析,以及启用自增长主键
        String[] tableNames = tableNameElement.split(",");
        String primaryKey = tableElement.hasAttribute("primaryKey") ? tableElement.getAttribute("primaryKey").toUpperCase() : null;
        // 记录是否主键自增,默认不是,(启用全局sequence handler)
        boolean autoIncrement = false;
        if (tableElement.hasAttribute("autoIncrement")) {
            autoIncrement = Boolean.parseBoolean(tableElement.getAttribute("autoIncrement"));
        }
        // 记录是否需要加返回结果集限制,默认需要加
        boolean needAddLimit = true;
        if (tableElement.hasAttribute("needAddLimit")) {
            needAddLimit = Boolean.parseBoolean(tableElement.getAttribute("needAddLimit"));
        }
        // 记录type,是否为global
        String tableTypeStr = tableElement.hasAttribute("type") ? tableElement.getAttribute("type") : null;
        int tableType = TableConfig.TYPE_GLOBAL_DEFAULT;
        if ("global".equalsIgnoreCase(tableTypeStr)) {
            tableType = TableConfig.TYPE_GLOBAL_TABLE;
        }
        // 记录dataNode,就是分布在哪些dataNode上
        String dataNode = tableElement.getAttribute("dataNode");
        TableRuleConfig tableRule = null;
        if (tableElement.hasAttribute("rule")) {
            String ruleName = tableElement.getAttribute("rule");
            tableRule = tableRules.get(ruleName);
            if (tableRule == null) {
                throw new ConfigException("rule " + ruleName + " is not found!");
            }
        }
        boolean ruleRequired = false;
        // 记录是否绑定有分片规则
        if (tableElement.hasAttribute("ruleRequired")) {
            ruleRequired = Boolean.parseBoolean(tableElement.getAttribute("ruleRequired"));
        }
        if (tableNames == null) {
            throw new ConfigException("table name is not found!");
        }
        // distribute函数,重新编排dataNode
        String distPrex = "distribute(";
        boolean distTableDns = dataNode.startsWith(distPrex);
        if (distTableDns) {
            dataNode = dataNode.substring(distPrex.length(), dataNode.length() - 1);
        }
        // 分表功能
        String subTables = tableElement.getAttribute("subTables");
        for (int j = 0; j < tableNames.length; j++) {
            String tableName = tableNames[j];
            TableRuleConfig tableRuleConfig = tableRule;
            if (tableRuleConfig != null) {
                // 对于实现TableRuleAware的function进行特殊处理  根据每个表新建个实例
                RuleConfig rule = tableRuleConfig.getRule();
                if (rule.getRuleAlgorithm() instanceof TableRuleAware) {
                    tableRuleConfig = (TableRuleConfig) ObjectUtil.copyObject(tableRuleConfig);
                    tableRules.remove(tableRuleConfig.getName());
                    String newRuleName = tableRuleConfig.getName() + "_" + tableName;
                    tableRuleConfig.setName(newRuleName);
                    TableRuleAware tableRuleAware = (TableRuleAware) tableRuleConfig.getRule().getRuleAlgorithm();
                    tableRuleAware.setRuleName(newRuleName);
                    tableRuleAware.setTableName(tableName);
                    tableRuleConfig.getRule().getRuleAlgorithm().init();
                    tableRules.put(newRuleName, tableRuleConfig);
                }
            }
            TableConfig table = new TableConfig(tableName, primaryKey, autoIncrement, needAddLimit, tableType, dataNode, getDbType(dataNode), (tableRuleConfig != null) ? tableRuleConfig.getRule() : null, ruleRequired, null, false, null, null, subTables);
            checkDataNodeExists(table.getDataNodes());
            // 检查分片表分片规则配置是否合法
            if (table.getRule() != null) {
                checkRuleSuitTable(table);
            }
            if (distTableDns) {
                distributeDataNodes(table.getDataNodes());
            }
            // 检查去重
            if (tables.containsKey(table.getName())) {
                throw new ConfigException("table " + tableName + " duplicated!");
            }
            // 放入map
            tables.put(table.getName(), table);
        }
        // 只有tableName配置的是单个表(没有逗号)的时候才能有子表
        if (tableNames.length == 1) {
            TableConfig table = tables.get(tableNames[0]);
            // process child tables
            processChildTables(tables, table, dataNode, tableElement);
        }
    }
    return tables;
}
Also used : NodeList(org.w3c.dom.NodeList) Element(org.w3c.dom.Element) TableRuleAware(io.mycat.route.function.TableRuleAware) ConfigException(io.mycat.config.util.ConfigException) TableConfigMap(io.mycat.config.model.TableConfigMap) TableRuleConfig(io.mycat.config.model.rule.TableRuleConfig) TableConfig(io.mycat.config.model.TableConfig) TableRuleConfig(io.mycat.config.model.rule.TableRuleConfig) RuleConfig(io.mycat.config.model.rule.RuleConfig)

Example 24 with TableConfig

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

the class DruidInsertParser method parserChildTable.

private RouteResultset parserChildTable(SchemaConfig schema, RouteResultset rrs, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException {
    TableConfig tc = schema.getTables().get(tableName);
    String joinKey = tc.getJoinKey();
    int joinKeyIndex = getJoinKeyIndex(insertStmt.getColumns(), joinKey);
    if (joinKeyIndex == -1) {
        String inf = "joinKey not provided :" + tc.getJoinKey() + "," + insertStmt;
        LOGGER.warn(inf);
        throw new SQLNonTransientException(inf);
    }
    if (isMultiInsert(insertStmt)) {
        String msg = "ChildTable multi insert not provided";
        LOGGER.warn(msg);
        throw new SQLNonTransientException(msg);
    }
    String joinKeyVal = insertStmt.getValues().getValues().get(joinKeyIndex).toString();
    String sql = insertStmt.toString();
    // try to route by ER parent partion key
    RouteResultset theRrs = RouterUtil.routeByERParentKey(null, schema, ServerParse.INSERT, sql, rrs, tc, joinKeyVal);
    if (theRrs != null) {
        rrs.setFinishedRoute(true);
        return theRrs;
    }
    // route by sql query root parent's datanode
    String findRootTBSql = tc.getLocateRTableKeySql().toLowerCase() + joinKeyVal;
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("find root parent's node sql " + findRootTBSql);
    }
    FetchStoreNodeOfChildTableHandler fetchHandler = new FetchStoreNodeOfChildTableHandler();
    String dn = fetchHandler.execute(schema.getName(), findRootTBSql, tc.getRootParent().getDataNodes());
    if (dn == null) {
        throw new SQLNonTransientException("can't find (root) parent sharding node for sql:" + sql);
    }
    if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("found partion node for child table to insert " + dn + " sql :" + sql);
    }
    return RouterUtil.routeToSingleNode(rrs, dn, sql);
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) FetchStoreNodeOfChildTableHandler(io.mycat.backend.mysql.nio.handler.FetchStoreNodeOfChildTableHandler) TableConfig(io.mycat.config.model.TableConfig) RouteResultset(io.mycat.route.RouteResultset)

Example 25 with TableConfig

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

the class DruidInsertParser method statementParse.

/**
 * 考虑因素:isChildTable、批量、是否分片
 */
@Override
public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) throws SQLNonTransientException {
    MySqlInsertStatement insert = (MySqlInsertStatement) stmt;
    String tableName = StringUtil.removeBackquote(insert.getTableName().getSimpleName()).toUpperCase();
    ctx.addTable(tableName);
    if (RouterUtil.isNoSharding(schema, tableName)) {
        // 整个schema都不分库或者该表不拆分
        RouterUtil.routeForTableMeta(rrs, schema, tableName, rrs.getStatement());
        rrs.setFinishedRoute(true);
        return;
    }
    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);
    } else {
        // childTable的insert直接在解析过程中完成路由
        if (tc.isChildTable()) {
            parserChildTable(schema, rrs, tableName, insert);
            return;
        }
        String partitionColumn = tc.getPartitionColumn();
        if (partitionColumn != null) {
            // 拆分表必须给出column list,否则无法寻找分片字段的值
            if (insert.getColumns() == null || insert.getColumns().size() == 0) {
                throw new SQLSyntaxErrorException("partition table, insert must provide ColumnList");
            }
            // 批量insert
            if (isMultiInsert(insert)) {
                // String msg = "multi insert not provided" ;
                // LOGGER.warn(msg);
                // throw new SQLNonTransientException(msg);
                parserBatchInsert(schema, rrs, partitionColumn, tableName, insert);
            } else {
                parserSingleInsert(schema, rrs, partitionColumn, tableName, insert);
            }
        }
    }
}
Also used : SQLNonTransientException(java.sql.SQLNonTransientException) SQLSyntaxErrorException(java.sql.SQLSyntaxErrorException) TableConfig(io.mycat.config.model.TableConfig) MySqlInsertStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement)

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