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);
}
}
}
}
}
}
}
}
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);
}
}
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;
}
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);
}
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);
}
}
}
}
Aggregations