1、重构代码,改用quartz做线程调度,实现HA

2、多个库的 向同一个库的表 同步数据 在同一个线程执行,保证不会造成死锁的情况,同时不会因为一个表同步事件过长而影响同一个库的其它表同步
3、部分特殊表通过 拦截器的方式 实现同步,如detection_set_info,meta_data。拦截器信息已配置到
table_sync_info 表中
4、重新整理nms 分库与主库 初始化语句及 同步配置表,初始化时
node_table.sync_status,event_record_library.db_id 的默认值需要修改为所在库的
id,id保存在sync_db_info 中,确保所有同步库 sync_db_info 表信息一致
This commit is contained in:
fangshunjian
2019-01-12 22:21:30 +06:00
parent af4f0910ba
commit c88b984af2
30 changed files with 17209 additions and 33 deletions

View File

@@ -2,13 +2,17 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="conf"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.7.0_80"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="lib" path="lib/log4j-1.2.15.jar"/>
<classpathentry kind="lib" path="lib/fastjson-1.2.47.jar"/>
<classpathentry kind="lib" path="lib/druid-1.0.29.jar"/>
<classpathentry kind="lib" path="lib/jfinal-3.4-bin-with-src.jar"/>
<classpathentry kind="lib" path="lib/c3p0-0.9.1.2.jar"/>
<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.13.jar"/>
<classpathentry kind="lib" path="lib/log4j-1.2.16.jar"/>
<classpathentry kind="lib" path="lib/quartz-2.2.3.jar" sourcepath="D:/装机软件/quartz-2.2.3-distribution/src"/>
<classpathentry kind="lib" path="lib/quartz-jobs-2.2.3.jar"/>
<classpathentry kind="lib" path="lib/slf4j-api-1.7.7.jar"/>
<classpathentry kind="lib" path="lib/slf4j-log4j12-1.7.7.jar"/>
<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.36.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,7 +1,7 @@
#\u4e3b\u5e93\u540c\u6b65\u5206\u5e93\u6570\u636e\u7ebf\u7a0b\u65f6\u95f4\u5dee
syncMaterToSlaveTime=30000
syncMaterToSlaveTime=10
#\u4e3b\u5e93\u540c\u6b65\u5206\u5e93\u6570\u636e\u7ebf\u7a0b\u65f6\u95f4\u5dee
syncSlaveToMaterTime=60000
syncSlaveToMaterTime=15
#从库向主库同步的线程池数量
slave.to.master.pool.num=3
#主库向从库同步的线程池数量

View File

@@ -1,10 +1,10 @@
log4j.rootLogger=DEBUG, stdout, file
log4j.rootLogger=INFO, stdout, file
#log4j.rootLogger=ERROR, stdout, file
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%n%-d{yyyy-MM-dd HH:mm:ss}%n[%p]-[Thread: %t]-[%C.%M()]: %m%n
log4j.appender.stdout.layout.ConversionPattern=%d %p (%F:%L) [%t] - <%m>%n
log4j.logger.com.nms=debug
# Output to the File
#log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
#log4j.appender.file.DatePattern='_'yyyy-MM-dd'.log'

View File

@@ -0,0 +1,28 @@
#################### quartz 相关配置文件 #########################
#Main Scheduler Settings
org.quartz.scheduler.instanceName=NMSSync
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true
org.quartz.scheduler.skipUpdateCheck=true
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=100
org.quartz.threadPool.threadCount=10
#Configure JDBC-JobStoreTX
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.acquireTriggersWithinLock=true
org.quartz.jobStore.clusterCheckinInterval = 30000
org.quartz.jobStore.dataSource=qzDS
#============================================================================
# Configure Datasources
#============================================================================
#JDBC驱动
org.quartz.dataSource.qzDS.driver=com.mysql.jdbc.Driver
#在程序里赋值
#org.quartz.dataSource.qzDS.URL=jdbc:mysql://localhost:3306/quartz
#org.quartz.dataSource.qzDS.user=root
#org.quartz.dataSource.qzDS.password=christmas258@

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

8346
nms_sync/sql/nms-master.sql Normal file

File diff suppressed because it is too large Load Diff

6452
nms_sync/sql/nms-slave1.sql Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,7 @@ import org.apache.log4j.Logger;
import com.jfinal.plugin.activerecord.ICallback;
public class SyncStoredProcedure implements ICallback{
private Logger logger=Logger.getLogger(this.getClass());
private static Logger logger=Logger.getLogger(SyncStoredProcedure.class);
private String proName;
private String tableName;
private String filedAndType;
@@ -27,25 +27,12 @@ public class SyncStoredProcedure implements ICallback{
public Object call(Connection conn) throws SQLException {
logger.info("开始调用存储过程任务");
CallableStatement proc=null;
try{
proc=conn.prepareCall("{call "+proName+"(?,?,?)}");
proc.setString(1,tableName);
proc.setString(2,filedAndType);
proc.setString(3, fileds);
proc.execute();
logger.info("调用存储过程任务结束");
} catch (Exception e){
logger.error("调用存储过程任务出现错误 存储过程名称"+proName+" 表名"+tableName+"参数 "+filedAndType+"------"+fileds);
logger.error("调用存储过程任务出现错误 ",e);
e.printStackTrace();
} finally{
if(conn!=null){
conn.close();
}
if(proc!=null){
proc.close();
}
}
proc=conn.prepareCall("{call "+proName+"(?,?,?)}");
proc.setString(1,tableName);
proc.setString(2,filedAndType);
proc.setString(3, fileds);
proc.execute();
logger.info("调用存储过程任务结束");
return null;
}
}

View File

@@ -0,0 +1,198 @@
package com.nms.job;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.ICallback;
import com.jfinal.plugin.activerecord.Record;
import com.nms.interceptor.SyncStoredProcedure;
import com.nms.job.SyncDataJob;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.SyncCommon;
/**
* check_type_info
* 主库向从库同步 update
* 1、update 更新操作 判断 state == 0监测 表是否已经创建,如果没有创建,新增表
* @author fang
*
*/
@SuppressWarnings("all")
public class CheckTypeInfoInterceptor implements Interceptor{
private static final Logger logger = Logger.getLogger(CheckTypeInfoInterceptor.class);
private TableSyncInfo tableInfo;
private SyncDbInfo from;
private SyncDbInfo to;
public void init(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
this.tableInfo = tableInfo;
this.from = from;
this.to = to;
}
@Override
public void exce(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
init(tableInfo, from, to);//将变量保存到 对象
final String idName = tableInfo.getIdName();
final String tableName = tableInfo.getTableName();
Integer mode = tableInfo.getMode();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
Integer event = tableInfo.getEvent();
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
if(event == 1) {//insertmetadata表主键生成方式为 mode = 1,insert 不需要删除 主键id
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
Long lastId = tableInfo.getLastId();
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, findRecord, batchSize);//添加新增
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else if (event == 2) {//update
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
boolean updateIdName = idName.equalsIgnoreCase(updateIds);//更新主键 是否和 查询主键一致
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
createTable(findRecord, tableInfo, from, to);;
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}else {
logger.warn(String.format("unknown event %s", event));
}
}
/**
* 检查创建表
*/
public void createTable(List<Record> findRecord,TableSyncInfo tableInfo, SyncDbInfo masterDb, SyncDbInfo slaveDb) {
for(Record record : findRecord) {
String creteState = record.get("CRETE_STATE");
String tableName = record.getStr("TABLE_NAME");
if("0".equals(creteState)) {//表创建
Record isExist = Db.use(slaveDb.getDbKey()).findFirst("select 1 count from information_schema.`TABLES` WHERE TABLE_SCHEMA = ? and UPPER(TABLE_NAME) = ?",slaveDb.getDatabaseName(),tableName);
if(isExist == null) {
//创建表数据
StringBuffer sqlSb= new StringBuffer();
StringBuffer cIndexFileds = new StringBuffer("data_check_time:seq_id:detection_set_info_id:");
List<Record> metadatas = Db.use(slaveDb.getDbKey()).find("select * from metadata where 1=1 and check_type_id=? and state = '0' order by show_num asc",record.getLong("ID"));
if(metadatas!=null && metadatas.size()>0) {
for(Record meta : metadatas) {
sqlSb.append(",").append(meta.get("filed_name")).append(" ").append(toMysqlType(meta.getStr("filed_type")));
if(meta.get("chart_state").equals("0")) {
cIndexFileds.append(meta.getStr("filed_name")).append(":");
}
}
sqlSb.deleteCharAt(0);
//调用存储过程创建表
Db.use(slaveDb.getDbKey()).execute(new SyncStoredProcedure("pro_createTable",tableName, sqlSb.toString(),cIndexFileds.toString()));
Record syncInfo = new Record();
record.set("table_name", tableName);
record.set("mode", 2);
record.set("id_name", "ID");
record.set("event",1);
record.set("last_id", 0);
record.set("db_id", masterDb.getId());//监测数据,分库向主库同步
record.set("last_date", new Date());
Db.use(slaveDb.getDbKey()).save("table_sync_info", syncInfo);//添加同步信息
logger.info("");
}
}
}
}
}
private static String toMysqlType(String type){
type = type.trim().toLowerCase();
if(type.startsWith("date")){
type = type.replaceAll("date", "datetime");
}else if(type.startsWith("number")){
type = type.replaceAll("number", "bigint");
}else if(type.startsWith("varchar")){
type = type.replaceAll("varchar2", "varchar");
}
return type;
}
}

View File

@@ -0,0 +1,248 @@
package com.nms.job;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.nms.job.SyncDataJob;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.SyncCommon;
/**
* 普通任务 mission_result_table146 特殊处理
* insert & update
* 从库 向 主库 同步,更新 mission_state_table
* @author fang
*
*/
@SuppressWarnings("all")
public class CommonMissionInterceptor implements Interceptor {
private static Logger logger = Logger.getLogger(CommonMissionInterceptor.class);
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //Java Date 类型数据格式化格式
// 线程变量记录周期任务结果修改的任务id
private Set<Long> updateMissionIds = new HashSet<Long>();
// 线程变量记录周期任务结果新增的任务id
private Set<Long> insertMissionIds = new HashSet<Long>();
private TableSyncInfo tableInfo;
private SyncDbInfo from;
private SyncDbInfo to;
public void init(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
this.tableInfo = tableInfo;
this.from = from;
this.to = to;
}
@Override
public void exce(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
init(tableInfo, from, to);//将变量保存到 对象
final String idName = tableInfo.getIdName();
final String tableName = tableInfo.getTableName();
Integer mode = tableInfo.getMode();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
Integer event = tableInfo.getEvent();
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
if(event == 1) {//insert
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
logger.debug(String.format("sql -> %s", sbSql.toString()));
Long lastId = tableInfo.getLastId();
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
final List<Record> insertList = new ArrayList<Record>();
final List<Record> updateList = new ArrayList<Record>();
for(Record r : findRecord) {//删除自增主键,不需要同步
Record exist = toDbPro.findFirst(String.format("select 1 from %s where %s = ? ", tableName,idName),r.get(idName));
if(exist == null) {//不存在
insertList.add(r);
insertMissionIds.add(r.getLong(idName));
}else {
updateList.add(r);
updateMissionIds.add(r.getLong(idName));
}
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, insertList, batchSize);//添加新增
toDbPro.batchUpdate(tableName, idName, updateList, batchSize);//更新
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else if (event == 2) {//update
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
boolean updateIdName = idName.equalsIgnoreCase(updateIds);//更新主键 是否和 查询主键一致
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
updateMissionIds.add(r.getLong(idName));
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}else {
logger.warn(String.format("unknown event %s", event));
}
//更新 mission_state_table 表的状态
updateMissionStateTableLoop();
}
/**
* 同步 loop mission result 表 之后 更新 mission_state_table 表的状态
*/
private void updateMissionStateTableLoop() {
for(Long id :insertMissionIds) {
statisticalHandle(id, true);
}
for(Long id :updateMissionIds) {
statisticalHandle(id, false);
}
}
/**
* 处理非周期任务的统计功能
*/
public void statisticalHandle(Long missionId,boolean isInsert) {
logger.info("根据当前任务id为:"+missionId+"开始统计");
// mission_state_table 状态值
Integer status = null;
List<Record> results = Db.use().find("select result from (\r\n" +
"(select result,mission_id from mission_result_table1 mrt) union all \r\n" +
"(select result,mission_id from mission_result_table4 mrt) union all \r\n" +
"(select result,mission_id from mission_result_table6 mrt)\r\n" +
") t \r\n" +
"left join mission_state_table mst on mst.mission_id = t.mission_id \r\n" +
"where mst.is_loop = 0 and mst.mission_id=?",missionId);
// 判断任务结果有没有状态值为3的 如果有 则任务状态为在下发
Record result = Db.use().findFirst("select t.mission_id,t.ok,t.fail,t.total from (\r\n" +
"(select mrt.mission_id,sum(CASE mrt.result when 0 THEN 1 ELSE 0 end) ok,sum(CASE mrt.result when 1 then 1 when -1 then 1 else 0 end) fail,count(mrt.seq_id) total from mission_result_table1 mrt group by mrt.mission_id) union all \r\n" +
"(select mrt.mission_id,sum(CASE mrt.result when 0 THEN 1 ELSE 0 end) ok,sum(CASE mrt.result when 1 then 1 when -1 then 1 else 0 end) fail,count(mrt.seq_id) total from mission_result_table4 mrt group by mrt.mission_id) union all \r\n" +
"(select mrt.mission_id,sum(CASE mrt.result when 0 THEN 1 ELSE 0 end) ok,sum(CASE mrt.result when 1 then 1 when -1 then 1 else 0 end) fail,count(mrt.seq_id) total from mission_result_table6 mrt group by mrt.mission_id)\r\n" +
") t \r\n" +
"left join mission_state_table mst on mst.mission_id = t.mission_id \r\n" +
"where mst.is_loop = 0 and t.mission_id = ?",missionId);
if(null!=result) {
Integer okCount = result.getInt("ok");
Integer failCount =result.getInt("fail");
Integer total =result.getInt("total");
if(okCount+failCount==total) {
if(failCount==0) {
status=30;
}else if(okCount==0) {
status=31;
}else {
status=32;
}
}else{
status=2;
}
logger.info("统计完成 修改mission_state_table状态为:"+status+" 总个数:"+total+"执行数:"+(okCount+failCount)+" 成功:"+okCount+" 失败:"+failCount+"");
String missionStateAutoDesc=null;
if(isInsert) {
Record missionStateTable = Db.use().findFirst("select * from mission_state_table where mission_id = ?",missionId);
if(null!=missionStateTable&&null!=missionStateTable.get("auto_desc")&&missionStateTable.getStr("auto_desc").length()>0) {
return;
}
missionStateAutoDesc=format.format(System.currentTimeMillis())+"i18n_server.MissionConstants.NOTICE_TASK_RUNNING_n81i </br>";
}
if(okCount+failCount==total) {
missionStateAutoDesc=format.format(System.currentTimeMillis())+" i18n_sserver.UpgradeService.sql.complate_n81i "+total+" i18n_sserver.UpgradeService.sql.executeNode_n81i "+okCount+" i18n_sserver.UpgradeService.sql.failed_n81i "+failCount;
}
String missionStateDesc="\r\n" +
"i18n_server.UpgradeService.sql.total_n81i "+total+" i18n_server.UpgradeService.sql.executeNode2_n81i</br> "+(total-okCount-failCount)+" i18n_server.UpgradeService.sql.unexecute_n81i</br>"+(okCount+failCount)+" i18n_server.UpgradeService.sql.execute_n81i【i18n_server.UpgradeService.sql.success_n81i "+okCount+" i18n_sserver.UpgradeService.sql.failed_n81i "+failCount+"";
Record missionStateTableResult =new Record();
missionStateTableResult.set("mission_id", missionId);
if(status!=null) {
missionStateTableResult.set("mission_state", status);
}
missionStateTableResult.set("mission_state_desc", missionStateDesc);
if(missionStateAutoDesc!=null) {
missionStateTableResult.set("auto_desc", missionStateAutoDesc);
}
//to 为主库
Db.use(to.getDbKey()).update("mission_state_table","mission_id",missionStateTableResult);
}
logger.info("修改mission_state_table信息完成");
}
}

View File

@@ -0,0 +1,238 @@
package com.nms.job;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.nms.job.SyncDataJob;
import com.nms.model.SetInfo;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.socket.SocketClientServeice;
import com.nms.util.SyncCommon;
/**
* detection_set_info 特殊处理
* insert & update
* 1、主库向 分库同步
* 2、主库同步完成后 socket 通知 dc
* @author fang
*
*/
@SuppressWarnings("all")
public class DetectionSetInfoInterceptor implements Interceptor {
private static Logger logger = Logger.getLogger(DetectionSetInfoInterceptor.class);
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //Java Date 类型数据格式化格式
/**
* 监控设置信息变更请求命令
*/
private static final String WEB_NOTICE_SET_INFO_ALERT = "char:setInfoAlert";
private TableSyncInfo tableInfo;
private SyncDbInfo from;
private SyncDbInfo to;
public void init(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
this.tableInfo = tableInfo;
this.from = from;
this.to = to;
}
@Override
public void exce(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
init(tableInfo, from, to);//将变量保存到 对象
init(tableInfo, from, to);//将变量保存到 对象
final String idName = tableInfo.getIdName();
final String tableName = tableInfo.getTableName();
Integer mode = tableInfo.getMode();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
Integer event = tableInfo.getEvent();
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
if(event == 1) {//insert
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
Long lastId = tableInfo.getLastId();
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
Set<Long> oldSetInfo = new HashSet<Long>();
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
StringBuilder wSb = new StringBuilder();
for(Record r : findRecord) {//删除自增主键,不需要同步
oldSetInfo.add(r.getLong(idName));
wSb.append(",").append("?");
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
wSb.deleteCharAt(0);
boolean tx = fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
if(tx) {
List<Record> newSetInfoList = Db.use(to.getDbKey()).find("select m.*,cti.id CHECK_TYPE_INFO_ID,cti.check_type_name CHECK_TYPE_INFO_NAME from detection_set_info m left join check_type_info cti on m.check_type_id=cti.id where m.id in ("+wSb.toString()+")",oldSetInfo.toArray());
noticDcSetInfo(newSetInfoList, null, tableInfo, from, to);
}
continue;
}
//没有数据,退出循环
break ;
}
}else if (event == 2) {//update
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
boolean updateIdName = idName.equalsIgnoreCase(updateIds);//更新主键 是否和 查询主键一致
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
//保存 监测设置 修改之前的记录
Set<Long> oldSetInfo = new HashSet<Long>();
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
StringBuilder wSb = new StringBuilder();
for(Record r : findRecord) {//删除自增主键,不需要同步
oldSetInfo.add(r.getLong(idName));
wSb.append(",").append("?");
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
wSb.deleteCharAt(0);
List<Record> oldSetInfoList = Db.use(to.getDbKey()).find("select m.*,cti.id CHECK_TYPE_INFO_ID,cti.check_type_name CHECK_TYPE_INFO_NAME from detection_set_info m left join check_type_info cti on m.check_type_id=cti.id where m.id in ("+wSb.toString()+")",oldSetInfo.toArray());
boolean tx = fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
if(tx) {
List<Record> newSetInfoList = Db.use(to.getDbKey()).find("select m.*,cti.id CHECK_TYPE_INFO_ID,cti.check_type_name CHECK_TYPE_INFO_NAME from detection_set_info m left join check_type_info cti on m.check_type_id=cti.id where m.id in ("+wSb.toString()+")",oldSetInfo.toArray());
noticDcSetInfo(newSetInfoList, oldSetInfoList, tableInfo, from, to);
}
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}else {
logger.warn(String.format("unknown event %s", event));
}
}
public void noticDcSetInfo(List<Record> newSetInfo,List<Record> oldSetInfo,TableSyncInfo tableInfo, SyncDbInfo masterDb, final SyncDbInfo slaveDb) {
Map<Long,Record> oldMap = new HashMap<Long,Record>();
if(oldSetInfo != null) {
for(Record r : oldSetInfo) {
oldMap.put(r.getLong("ID"), r);
}
}
//获取当前分库连接的dc的IP信息
final String serverIp = PropKit.use("socket.properties").get("db"+slaveDb.getIp());
logger.info("获取socket连接ip信息为"+serverIp);
//根据数据库分库dc ip信息获取数据库相关实体信息
final Record serverTableInfo = Db.findFirst("select * from server_table where server_ip = ? and server_state=0 ",serverIp);
for(Record newRecord : newSetInfo) {
Record oldRecord = oldMap.get(newRecord.getLong("ID"));
SetInfo o=null;
if(oldRecord != null) {
o = new SetInfo();
o.setId(oldRecord.getLong("ID"));
o.setCheckTypeId(oldRecord.getLong("CHECK_TYPE_INFO_ID"));
o.setCheckTypeName(oldRecord.getStr("CHECK_TYPE_INFO_Name"));
o.setProcessIden(oldRecord.getStr("PROCESS_IDEN"));
o.setNodeGroupsId(oldRecord.getStr("NODE_GROUPS_ID"));
o.setNodeIpsId(oldRecord.getStr("NODE_IPS_ID"));
o.setCheckWay(oldRecord.getStr("CHECK_WAY"));
}
SetInfo n = new SetInfo();
n.setId(newRecord.getLong("ID"));
n.setCheckTypeId(newRecord.getLong("CHECK_TYPE_INFO_ID"));
n.setCheckTypeName(newRecord.getStr("CHECK_TYPE_INFO_Name"));
n.setProcessIden(newRecord.getStr("PROCESS_IDEN"));
n.setNodeGroupsId(newRecord.getStr("NODE_GROUPS_ID"));
n.setNodeIpsId(newRecord.getStr("NODE_IPS_ID"));
n.setCheckWay(newRecord.getStr("CHECK_WAY"));
final JSONObject jObject = new JSONObject();
jObject.put("old", o);
jObject.put("new", n);
new Thread(new Runnable(){
@Override
public void run() {
try {
new SocketClientServeice(serverIp).sendInfoToServer(WEB_NOTICE_SET_INFO_ALERT,jObject.toString());
logger.info(String.format("监测设置变更通知成功data: %s", jObject.toString()));
} catch (Exception e) {
Record eventRecordLibrary=new Record();
eventRecordLibrary.set("record_command", WEB_NOTICE_SET_INFO_ALERT);
eventRecordLibrary.set("record_content", jObject.toString());
eventRecordLibrary.set("record_type", "W2S");
eventRecordLibrary.set("state", 1l);
eventRecordLibrary.set("nmsserver_id", serverTableInfo.get("id"));
eventRecordLibrary.set("create_time", new Date());
Db.use(slaveDb.getDbKey()).save("event_record_library", eventRecordLibrary);
logger.warn("Monitoring setting to change communication anomalies,",e);
}
}
}).start();
}
}
}

View File

@@ -0,0 +1,13 @@
package com.nms.job;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
/**
* 名字叫拦截器,但功能和拦截器不同,如果配置了拦截器则只调用此 exce 方法,不在执行下面的 insert update 等
* @author ThinkPad
*
*/
public interface Interceptor {
void exce(final TableSyncInfo tableInfo,final SyncDbInfo from ,final SyncDbInfo to);
}

View File

@@ -0,0 +1,344 @@
package com.nms.job;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.nms.job.SyncDataJob;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.SyncCommon;
/**
* loopmission_state_table 特殊处理
* insert & update
* 1、分库向主库同步
* @author fang
*
*/
@SuppressWarnings("all")
public class LoopStateTableInterceptor implements Interceptor {
private static Logger logger = Logger.getLogger(LoopStateTableInterceptor.class);
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //Java Date 类型数据格式化格式
// 线程变量记录周期任务结果修改的任务id
private Set<Long> loopUpdateMissionIds = new HashSet<Long>();
// 线程变量记录周期任务结果新增的任务id
private Set<Long> loopInsertMissionIds = new HashSet<Long>();
private TableSyncInfo tableInfo;
private SyncDbInfo from;
private SyncDbInfo to;
public void init(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
this.tableInfo = tableInfo;
this.from = from;
this.to = to;
}
@Override
public void exce(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
init(tableInfo, from, to);//将变量保存到 对象
init(tableInfo, from, to);//将变量保存到 对象
final String idName = tableInfo.getIdName();
final String tableName = tableInfo.getTableName();
Integer mode = tableInfo.getMode();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
Integer event = tableInfo.getEvent();
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
if(event == 1) {//insert
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
Long lastId = tableInfo.getLastId();
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
final List<Record> insertList = new ArrayList<Record>();
final List<Record> updateList = new ArrayList<Record>();
for(Record r : findRecord) {//删除自增主键,不需要同步
Record exist = toDbPro.findFirst(String.format("select 1 from %s where %s = ? ", tableName,idName),r.get(idName));
if(exist == null) {//不存在
insertList.add(r);
loopInsertMissionIds.add(r.getLong(idName));
}else {
updateList.add(r);
loopUpdateMissionIds.add(r.getLong(idName));
}
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, insertList, batchSize);//添加新增
toDbPro.batchUpdate(tableName, idName, updateList, batchSize);//更新
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else if (event == 2) {//update
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
boolean updateIdName = idName.equalsIgnoreCase(updateIds);//更新主键 是否和 查询主键一致
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
loopUpdateMissionIds.add(r.getLong(idName));
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}else {
logger.warn(String.format("unknown event %s", event));
}
//更新 mission_state_table 表的状态
updateMissionStateTableLoop();
}
/**
* 同步 loop mission result 表 之后 更新 mission_state_table 表的状态
*/
private void updateMissionStateTableLoop() {
for(Long id :loopInsertMissionIds) {
statisticalLoopHandle(id, true);
}
for(Long id :loopUpdateMissionIds) {
statisticalLoopHandle(id, false);
}
}
/**
* 处理周期任务的统计功能
*/
public void statisticalLoopHandle(Long curMissionId,boolean isInsert) {
Record loopmissionStateTableInfo = Db.use().findFirst("select * from loopmission_state_table where cur_mission_id = ? ",curMissionId);
String missionDesc="";
Integer status=null;
String autoDesc="";
Record missionTableInfo =null;
Integer missionState = null;
// 判断任务状态为1 根据同步结果数据 修改为状态2 正在执行
if(null!=loopmissionStateTableInfo) {
missionTableInfo = Db.use().findFirst("select * from mission_state_table where mission_id = ? ",loopmissionStateTableInfo.getLong("mission_id"));
if(null!=missionTableInfo&&missionTableInfo.getInt("mission_state").equals(1)&&isInsert) {
missionTableInfo.set("mission_state",2);
if(null==missionTableInfo.getStr("auto_desc")) {
missionTableInfo.set("auto_desc", format.format(System.currentTimeMillis())+"i18n_server.LoadNewMissionThread.missionStart_n81i");
}
//更新 主库 mission_state_table 表 任务执行描述
Db.use(to.getDbKey()).update("mission_state_table", missionTableInfo);
}
// 修改周期任务的执行状态
Record result = null;
// 周期任务时进行统计
if(loopmissionStateTableInfo.getInt("mission_state").equals(7)) {
result=Db.use().findFirst("select lmst.mission_id missionId, t.ok, t.fail, t.total\r\n" +
"from (select mrt.mission_id, \r\n" +
"ifnull(sum(case mrt.result when 7 then 1 else 0 end), 0) ok, \r\n" +
"ifnull(sum(case mrt.result when 4 then 1 else 0 end), 0) fail, \r\n" +
"count(mrt.seq_id) total \r\n" +
"from mission_result_table4 mrt \r\n" +
"group by mrt.mission_id) t \r\n" +
"left join (select max(lst.cur_mission_id) cur_mission_id, lst.mission_id \r\n" +
"from mission_result_table4 mrt4 \r\n" +
"left join loopmission_state_table lst on mrt4.mission_id = lst.cur_mission_id \r\n" +
"group by lst.mission_id) lmst \r\n" +
"on lmst.cur_mission_id = t.mission_id \r\n" +
"left join mission_state_table mst \r\n" +
"on mst.mission_id = lmst.mission_id \r\n" +
"where lmst.cur_mission_id is not null and mst.is_loop=1 \r\n" +
"and mst.mission_id = ? ", loopmissionStateTableInfo.getLong("mission_id"));
}else {
result=Db.use().findFirst("select lmst.mission_id missionId, t.ok, t.fail, t.total\r\n" +
"from (select mrt.mission_id, \r\n" +
"ifnull(sum(case mrt.result when 0 then 1 else 0 end), 0) ok, \r\n" +
"ifnull(sum(case mrt.result when 1 then 1 when -1 then 1 else 0 end), 0) fail, \r\n" +
"count(mrt.seq_id) total \r\n" +
"from mission_result_table4 mrt \r\n" +
"group by mrt.mission_id) t \r\n" +
"left join (select max(lst.cur_mission_id) cur_mission_id, lst.mission_id \r\n" +
"from mission_result_table4 mrt4 \r\n" +
"left join loopmission_state_table lst on mrt4.mission_id = lst.cur_mission_id \r\n" +
"group by lst.mission_id) lmst \r\n" +
"on lmst.cur_mission_id = t.mission_id \r\n" +
"left join mission_state_table mst \r\n" +
"on mst.mission_id = lmst.mission_id \r\n" +
"where lmst.cur_mission_id is not null and mst.is_loop=1 \r\n" +
"and mst.mission_id = ? ", loopmissionStateTableInfo.getLong("mission_id"));
}
if(null!=result) {
if(null!=result.get("missionId")&&result.getStr("missionId").length()>0) {
Long ok = result.getLong("ok");
Long fail =result.getLong("fail");
Long total = result.getLong("total");
missionDesc="i18n_server.UpgradeService.sql.cycle_n81i "+total+" i18n_server.UpgradeService.sql.executeNode2_n81i</br>"+(total-ok-fail)+" i18n_server.UpgradeService.sql.unexecute_n81i</br>"+(ok+fail)+" i18n_server.UpgradeService.sql.execute_n81i【i18n_server.UpgradeService.sql.success_n81i "+ok+" i18n_sserver.UpgradeService.sql.failed_n81i "+fail+"";
}
}
if(isInsert) {
missionState = loopmissionStateTableInfo.getInt("mission_state");
Integer missionTableInfoState = missionTableInfo.getInt("mission_state");
switch(missionState) {
case(3):
Record findFirst = Db.use().findFirst("select COUNT(*) count from loopmission_state_table where mission_id = ? and mission_state=0",loopmissionStateTableInfo.getLong("mission_id"));
if(findFirst.getInt("count").equals(0)&&missionTableInfoState!=3) {
status=3;
autoDesc=format.format(System.currentTimeMillis())+"i18n_server.UpgradeService.sql.revoke_n81i";
}
break;
case(4):
if(missionTableInfoState!=4) {
status=4;
autoDesc=format.format(System.currentTimeMillis())+" Task execution failure ";
}
break;
case(6):
if(missionTableInfoState!=6) {
status=6;
autoDesc=format.format(System.currentTimeMillis())+"Task revocation start execute";
}
break;
case(7):
if(missionTableInfoState!=7) {
status=7;
autoDesc=format.format(System.currentTimeMillis())+"i18n_server.UpgradeService.sql.revoke_n81i";
}
break;
}
}else {
missionState = loopmissionStateTableInfo.getInt("mission_state");
Integer missionTableInfoState = missionTableInfo.getInt("mission_state");
switch(missionState) {
case(3):
Record findFirst = Db.use().findFirst("select COUNT(*) count from loopmission_state_table where mission_id = ? and mission_state=0",loopmissionStateTableInfo.getLong("mission_id"));
if(findFirst.getInt("count").equals(0)&&missionTableInfoState!=3&&missionTableInfoState!=5&&missionTableInfoState!=6&&missionTableInfoState!=7) {
status=3;
autoDesc=format.format(System.currentTimeMillis())+"i18n_server.UpgradeService.sql.revoke_n81i";
}
break;
case(2):
if(missionTableInfoState!=6&&missionTableInfoState!=5&&missionTableInfoState!=7) {
status=2;
}
break;
case(6):
status=6;
if(missionTableInfoState!=6) {
autoDesc=format.format(System.currentTimeMillis())+"Task revocation start execute";
}
break;
case(7):
Record find = Db.use().findFirst("\r\n" +
"\r\n" +
"select count(*) count \r\n" +
" from (\r\n" +
" select lmst.mission_id, \r\n" +
" sum(case lmst.mission_state when 3 then 1 when 7 then 1 else 0 end) ok,-- //正常执行完成的周期,撤销完成的周期\r\n" +
" sum(case lmst.mission_state when 4 then 1 else 0 end) fail,-- //未能执行的周期\r\n" +
" count(lmst.cur_mission_id) total\r\n" +
" from loopmission_state_table lmst\r\n" +
" group by lmst.mission_id\r\n" +
" ) t\r\n" +
" left join mission_state_table mst on mst.mission_id = t.mission_id\r\n" +
" where t.ok + t.fail = t.total\r\n" +
" and ifnull(mst.mission_id, -1) <> -1\r\n" +
" and mst.is_loop = 1\r\n" +
" and mst.mission_state not in (3, 7, 4) and mst.mission_id=?",missionTableInfo.getLong("mission_id"));
if(null!=find&&find.getInt("count")!=0) {
status=7;
}
if(missionTableInfoState!=7) {
autoDesc=format.format(System.currentTimeMillis())+"i18n_server.UpgradeService.sql.revoke_n81i";
}
break;
}
}
Record missionStateTableResult =new Record();
missionStateTableResult.set("mission_id", loopmissionStateTableInfo.get("mission_id"));
if(status!=null) {
missionStateTableResult.set("mission_state", status);
}
if(missionDesc.length()>0&&null!=missionState) {
missionStateTableResult.set("mission_state_desc",missionDesc);
}
if(autoDesc.length()>0) {
missionStateTableResult.set("auto_desc",autoDesc);
}
//同步更新 主库 mission_state_table 任务执行描述信息
Db.use(to.getDbKey()).update("mission_state_table","mission_id",missionStateTableResult);
}
}
}

View File

@@ -0,0 +1,177 @@
package com.nms.job;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import com.alibaba.fastjson.JSON;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.nms.job.SyncDataJob;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.SyncCommon;
/**
* metadata 表
* insert & update
* 1、metadata 表insert 时判断是否已经创建了 表,如果没有创建表则不用特殊处理
* 2、metadata 表update 不需要更新 表结构
* @author fang
*
*/
@SuppressWarnings("all")
public class MetaDataInterceptor implements Interceptor{
private static final Logger logger = Logger.getLogger(MetaDataInterceptor.class);
private TableSyncInfo tableInfo;
private SyncDbInfo from;
private SyncDbInfo to;
public void init(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
this.tableInfo = tableInfo;
this.from = from;
this.to = to;
}
@Override
public void exce(final TableSyncInfo tableInfo, final SyncDbInfo from, final SyncDbInfo to) {
init(tableInfo, from, to);//将变量保存到 对象
init(tableInfo, from, to);//将变量保存到 对象
final String idName = tableInfo.getIdName();
final String tableName = tableInfo.getTableName();
Integer mode = tableInfo.getMode();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
Integer event = tableInfo.getEvent();
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
if(event == 1) {//insertmetadata表主键生成方式为 mode = 1,insert 不需要删除 主键id
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
Long lastId = tableInfo.getLastId();
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, findRecord, batchSize);//添加新增
for(Record r : findRecord) {
tableFiledSync(r.getLong("id"), tableInfo, from, to);
}
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else if (event == 2) {//update
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
boolean updateIdName = idName.equalsIgnoreCase(updateIds);//更新主键 是否和 查询主键一致
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}else {
logger.warn(String.format("unknown event %s", event));
}
}
/**
* 同步 meta_data 表结构字段
* @param mdId
*/
public void tableFiledSync(Long mdId,TableSyncInfo tableInfo, SyncDbInfo masterDb, SyncDbInfo slaveDb) {
Record record = Db.use(slaveDb.getDbKey()).findFirst("select m.*,cti.table_name from metadata m left join check_type_info cti on m.check_type_id=cti.id where m.id = ? ",mdId);
Record isExist = Db.use(slaveDb.getDbKey()).findFirst("select 1 count from information_schema.`TABLES` WHERE TABLE_SCHEMA = ? and UPPER(TABLE_NAME) = ?",slaveDb.getDatabaseName(),record.get("table_name"));
//向数据库中添加新的字段
if(isExist != null){
StringBuffer sqlString = new StringBuffer("alter table ");
sqlString.append(record.getStr("table_name").toUpperCase());
sqlString.append(" add(");
sqlString.append(record.getStr("filed_name")+" "+ toMysqlType(record.getStr("filed_type"))+")");
//执行添加字段
int resu =Db.use(slaveDb.getDbKey()).update(sqlString.toString());
logger.info(String.format("alter sql - > %s ,result : %s ",sqlString,resu));
}
}
private static String toMysqlType(String type){
type = type.trim().toLowerCase();
if(type.startsWith("date")){
type = type.replaceAll("date", "datetime");
}else if(type.startsWith("number")){
type = type.replaceAll("number", "bigint");
}else if(type.startsWith("varchar")){
type = type.replaceAll("varchar2", "varchar");
}
return type;
}
}

View File

@@ -0,0 +1,416 @@
package com.nms.job;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.DbPro;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.activerecord.Record;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.StopWatch;
import com.nms.util.SyncCommon;
/**
* 同步数据
* @author fang
*
*/
@DisallowConcurrentExecution
public class SyncDataJob implements Job{
private static final Logger logger = Logger.getLogger(SyncDataJob.class);
@Override
@SuppressWarnings("unchecked")
public void execute(JobExecutionContext context) throws JobExecutionException {
JobDetail jobDetail = context.getJobDetail();
//从jobdatamap 中取到 tablename,fromdb,todb信息
JobDataMap jobDataMap = jobDetail.getJobDataMap();
String tableName = jobDataMap.getString("tableName");
List<SyncDbInfo> fromDb = (List<SyncDbInfo>) jobDataMap.get("fromDb");
SyncDbInfo toDb = (SyncDbInfo) jobDataMap.get("toDb");
//同步表
syncTable(tableName, fromDb, toDb);
}
/**
* 普通通用逻辑的同步表
* 处理一对多的情况,防止数据库死锁
* 多对一 则直接 拆分为 一对一
* @param tableName
* @param fromDb
* @param toDb
*/
public void syncTable(String tableName,List<SyncDbInfo> fromDb,SyncDbInfo toDb) {
StopWatch sw = new StopWatch();
sw.tag("start");
for(SyncDbInfo from : fromDb) {
sw.tag("from-start");
//获取同步表信息 tableSyncInfo
String sql = "select * from table_sync_info tsi where tsi.db_id = ? and tsi.table_name = ? order by tsi.event";//按event排序保证insert,update,delete顺序
List<TableSyncInfo> tableSyncInfo = new TableSyncInfo().use(from.getDbKey()).find(sql, toDb.getId(),tableName);//当前表有哪些需要同步
if(tableSyncInfo != null &&tableSyncInfo.size() > 0) {
boolean allDataSync = false;//是否执行了全量同步
TableSyncInfo temp = null;
try {
for(TableSyncInfo tableInfo : tableSyncInfo) {
long tcount = 0;
temp = tableInfo;
sw.tag("info-start");
String interceptor = tableInfo.getInterceptor();
if(StrKit.notBlank(interceptor)) {//如果 有 interceptor 直接使用 interceptor 同步,不在执行下面的同步代码
Class<?> inCls = Class.forName(interceptor);
Interceptor newInstance = (Interceptor)inCls.newInstance();
newInstance.exce(tableInfo, from, toDb);
continue;
}
Integer event = tableInfo.getEvent();
switch (event) {
case 1:
//如果 last_id 为 -1truncate-2 delete
allDataSync = syncAllData(tableName, tableInfo, from, toDb);
if(allDataSync) {//执行了全量同步
tableInfo.setLastId(0L);
}
tcount = eventInsert(tableName,tableInfo, from, toDb); break;
case 2:
if(allDataSync) {//执行了全量同步,再次全量更新
tableInfo.setLastId(0L);
}
tcount = eventUpdate(tableName,tableInfo, from, toDb); break;
case 3:
if(allDataSync) {//执行了全量同步,再次全量删除
tableInfo.setLastId(0L);
}
tcount = eventDelete(tableName,tableInfo, from, toDb); break;
default:
logger.warn(String.format("unknown event : %s,tableName: %s", event,tableName));
break;
}
sw.tag("info-end");
logger.debug(String.format("耗时统计,%s-同步完成tableName : %s , toDb : %s ,fromDb : %s , total : %s ,耗时:%s", tableInfo.getEventStr(),tableName,toDb.getDbKey(),from.getDbKey(),tcount,sw.timeBetween("info-end", "info-start")));
}
} catch (Exception e) {
logger.error(String.format("同步异常tableName : %s,evnet : %s ,from : %s, to : %s ", temp.getTableName(),temp.getEventStr(),from.getDbKey(),toDb.getDbKey()),e);
}
}
sw.tag("from-end");
logger.debug(String.format("耗时统计表同步完成tableName : %s , toDb : %s ,fromDb : %s , 耗时:%s", tableName,toDb.getDbKey(),from.getDbKey(),sw.timeBetween("from-end", "from-start")));
}
sw.tag("end");
logger.debug(String.format("耗时统计库同步完成tableName : %s , toDb : %s ,fromDbSize : %s , 耗时:%s", tableName,toDb.getDbKey(),fromDb.size(),sw.timeBetween("end", "start")));
}
/**
* inset 同步
* @param tableInfo
* @param from
* @param to
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public long eventInsert(final String tableName,final TableSyncInfo tableInfo,SyncDbInfo from ,SyncDbInfo to) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
long count = 0;
String idName = tableInfo.getIdName();
Integer mode = tableInfo.getMode();
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long fromDbId = from.getId();// from db id
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
Long lastId = tableInfo.getLastId();
if(StrKit.notBlank(idName)) {//主键自增
StringBuilder sbSql = (mode == 2 ? SyncCommon.insertModeTwoSql(tableInfo) : SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo));
logger.debug(String.format("sql -> %s", sbSql.toString()));
final Integer batchSize = tableInfo.getBatchSize();
insert:while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
count += findRecord.size();
lastId = (mode==2? findRecord.get(findRecord.size()-1).getLong(idName) : findRecord.get(findRecord.size()-1).getLong("tableeventlogid"));
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {
//node_table表涉及双向同步添加同步库 id
if("node_table".equalsIgnoreCase(tableName)) {
r.set("sync_status",fromDbId);
}
if("event_record_library".equalsIgnoreCase(tableName)) {
//设置同步数据所在数据库的id以及所在原来表的id 用于修改和删除 -1为中心或主库
r.set("old_id",r.get(idName));
r.set("db_id", fromDbId);
r.remove(idName);//删除主键,防止主键冲突
}
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
if("detection_info_new".equalsIgnoreCase(tableName)) {
//detection_info_new insert 方式,先删除相同 DETECTION_SET_INFO_ID SEQ_ID 的记录,在插入
String delColumns = "DETECTION_SET_INFO_ID,SEQ_ID";
String delSql = SyncCommon.genDelSql(tableName, delColumns,null);
toDbPro.batch(delSql, delColumns, findRecord, batchSize);//删除
}
toDbPro.batchSave(tableName, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break insert;
}
}else {
//mode=0需要使用触发器更新 table_event_log 表同步时需要关联table_event_log 表 mode=1主键为自定义不重复主键
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
final Integer batchSize = tableInfo.getBatchSize();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
count += findRecord.size();
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
for(Record r : findRecord) {//删除自增主键,不需要同步
if("event_record_library".equalsIgnoreCase(tableName)) {
//设置同步数据所在数据库的id以及所在原来表的id 用于修改和删除 -1为中心或主库
r.set("old_id",r.get(idName));
r.set("db_id", fromDbId);
r.remove(idName);//删除主键,防止主键冲突
}
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
r.remove("tableeventlogid");
}
tableInfo.setLastId(lastId);//最后更新的id
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchSave(tableName, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
}else {//没有数据,退出循环
break ;
}
}
}else {//多主键的更新,需要每条查询,暂不实现
}
}
return count;
}
/**
* update 同步
* @param tableInfo
* @param from
* @param to
*/
public long eventUpdate(final String tableName,final TableSyncInfo tableInfo,SyncDbInfo from ,SyncDbInfo to) {
long count = 0;
final String idName = tableInfo.getIdName();//查询主键
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
//排除 insertupdate 字段
String excludeNames = tableInfo.getExcludeNames();
String[] excludeNameArr = StrKit.notBlank(excludeNames)? excludeNames.split(",") :null;
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
final Integer batchSize = tableInfo.getBatchSize();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.getSelectSqlLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
count += findRecord.size();
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
if(excludeNameArr != null) {//删除排除字段,不需要同步
for(String exclude : excludeNameArr) {
r.remove(exclude);
}
}
if("mission_state_table".equalsIgnoreCase(tableName)) {
// 主库同步任务状态表 如果状态修改不是周期停用的话 将状态字段的修改过滤
if(!(r.getInt("mission_state").equals(5)||r.getInt("mission_state").equals(1))) {
r.remove("mission_state");
}
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batchUpdate(tableName, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
continue;
}
//没有数据,退出循环
break ;
}
}else {//多主键的更新,需要每条查询,暂不实现
}
return count;
}
/**
* delete 同步
* 1、delete 的where 条件用于更新 目标的 做限制条件
* @param tableInfo
* @param from
* @param to
*/
public long eventDelete(final String tableName,final TableSyncInfo tableInfo,SyncDbInfo from ,SyncDbInfo to) {
long count = 0;
final String idName = tableInfo.getIdName();//查询主键
final String updateIds = StrKit.notBlank(tableInfo.getUpdateIds())?tableInfo.getUpdateIds():idName ;//更新主键多个逗号分隔如果没有配置updateIds ,默认为 idName
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
final Integer batchSize = tableInfo.getBatchSize();
String where = tableInfo.getWhere();
Long fromDbId = from.getId();
if(StrKit.notBlank(idName)) {//单一主键通过table_event_log表 关联查询
StringBuilder sbSql = SyncCommon.delSelectLeftJoinEventLog(tableInfo);
Long lastId = tableInfo.getLastId();
//生成delete sql 语句
final String delSql = SyncCommon.genDelSql(tableName, updateIds, where);
while(true) {
final List<Record> findRecord = fromDbPro.find(sbSql.toString(), lastId,batchSize);
if(findRecord != null && findRecord.size() > 0) {
count += findRecord.size();
lastId = findRecord.get(findRecord.size()-1).getLong("tableeventlogid");
tableInfo.setLastId(lastId);//最后更新的id
for(Record r : findRecord) {//删除自增主键,不需要同步
r.remove("tableeventlogid");
r.set("db_id", fromDbId);//添加 db_id
if("event_record_library".equalsIgnoreCase(tableName)) {
r.set("old_id",r.getLong(idName));
}
}
fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.batch(delSql, updateIds, findRecord, batchSize);
tableInfo.setLastDate(new Date());//最后更新时间
fromDbPro.update("table_sync_info", tableInfo.toRecord());
return true;
}
});
}
});
}else {//没有数据,退出循环
break ;
}
}
}else {//多主键的更新,需要每条查询,暂不实现
}
return count;
}
/**
* 全量同步,首先删除表中的内容
* event= 1 and last_id = -1 : truncate, last_id = -2 : delete from table where
* @param tableName 表名
* @param tableInfo 表同步配置信息
* @param fromDbPro from数据库信息
* @param toDbPro to数据库信息
*/
public boolean syncAllData(final String tableName,final TableSyncInfo tableInfo,final SyncDbInfo from ,final SyncDbInfo to) {
final DbPro fromDbPro = Db.use(from.getDbKey());
final DbPro toDbPro = Db.use(to.getDbKey());
Long lastId = tableInfo.getLastId();
final StringBuilder sql = new StringBuilder();
if(lastId == -1) {//trancate 表
sql.append("TRUNCATE ").append(tableName);
}else if (lastId == -2) {
String where = tableInfo.getWhere();
sql.append("delete from ").append(tableName);
if(StrKit.notBlank(where)) {
sql.append(" where ").append(where);
}
}
if(sql.length() > 0) {
toDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
return fromDbPro.tx(new IAtom() {
@Override
public boolean run() throws SQLException {
toDbPro.delete(sql.toString());
fromDbPro.update("update table_sync_info set last_id = 0 where table_name = ?" ,tableName);
return true;
}
});
}
});
return true;
}
return false;
}
}

View File

@@ -0,0 +1,192 @@
package com.nms.main;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.nms.job.SyncDataJob;
import com.nms.model.SyncDbInfo;
import com.nms.model.TableSyncInfo;
import com.nms.util.QuartzUtils;
/**
* 数据同步主功能 相当于主动推送操作
* @author Administrator
*
*/
public class StartUp{
private static Logger logger = Logger.getLogger(StartUp.class);
//druid 配置文件路径
public static final String DRUID_CONFIG_FILE_PATH;
public static Scheduler SCHEDULER;
static {
URL urlObj = StartUp.class.getClassLoader().getResource("druid.properties");
if(urlObj==null){
System.err.println("找不到配置文件druid.properties");
logger.error("No configuration file can be found: druid.properties");
System.exit(1);
}
DRUID_CONFIG_FILE_PATH = urlObj.getPath().replaceAll("%20", " ");
logger.debug(String.format("druid配置文件路径", DRUID_CONFIG_FILE_PATH));
}
public static void main(String[] args) {
logger.info("同步程序开始启动");
try {
//初始化数据源
List<SyncDbInfo> dataSource = initDataSource();
//初始化 定时器
initScheduler();
//加载同步表信息,添加定时任务
initSyncTable(dataSource);
//程序关闭时,停掉 scheduler
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
SCHEDULER.shutdown();
} catch (Exception e) {
logger.error("SCHEDULER shutdown error",e);
}
}
});
} catch(Exception e) {
logger.error("数据同步启动发生异常",e);
System.exit(1);
}
}
/**
* 初始化 定时器
*/
private static void initScheduler() {
//初始化定时器
Properties quartzConfig = PropKit.use("quartz.properties").getProperties();
//org.quartz.dataSource.qzDS.URL
//org.quartz.dataSource.qzDS.user
//org.quartz.dataSource.qzDS.password
Prop prop = PropKit.use("db.properties");
quartzConfig.put("org.quartz.dataSource.qzDS.URL", prop.get("dburl"));
quartzConfig.put("org.quartz.dataSource.qzDS.user", prop.get("dbusername"));
quartzConfig.put("org.quartz.dataSource.qzDS.password", prop.get("dbpassword"));
try {
SCHEDULER = QuartzUtils.createScheduler(quartzConfig);
} catch (Exception e) {
logger.error("Scheduler init error",e);
System.exit(1);
}
}
/**
* 初始化数据源
* @return
*/
public static List<SyncDbInfo> initDataSource() {
//从配置文件获取数据库连接信息
PropKit.use("db.properties");
//创建主数据库数据源
DruidPlugin masterDruid=new DruidPlugin(PropKit.get("dburl"),PropKit.get("dbusername"),PropKit.get("dbpassword"));
masterDruid.setInitialSize(1);
masterDruid.setMaxActive(1);
masterDruid.setMinIdle(1);
masterDruid.setMaxWait(Integer.valueOf(PropKit.get("dbMaxWait")));
ActiveRecordPlugin masterArp=new ActiveRecordPlugin("masterDataSource",masterDruid);
masterArp.setShowSql(Boolean.valueOf(PropKit.get("dbShowSql")));
masterDruid.start();
masterArp.start();
logger.info("master datasource connection ok ");
List<SyncDbInfo> syncDbInfos = SyncDbInfo.dao.use("masterDataSource").find("select * from sync_db_info");
createConn(syncDbInfos);//初始化各个分库
logger.info(String.format("数据源初始化完成datasource total : %s ", syncDbInfos.size()));
return syncDbInfos;
}
/**
* 初始化同步信息,创建定时任务
* @param syncDbInfos
* @throws SchedulerException
*/
public static void initSyncTable(List<SyncDbInfo> syncDbInfos) throws SchedulerException {
String sql = "SELECT * FROM table_sync_info group by db_id,table_name order by id";
Map<Long,SyncDbInfo> syncDbIdMap = new HashMap<Long,SyncDbInfo>();
//key -> dbId-tableName
Map<String,List<SyncDbInfo>> toFromMap = new LinkedHashMap<String,List<SyncDbInfo>>();
for(SyncDbInfo dbInfo :syncDbInfos) {
List<TableSyncInfo> tableList = new TableSyncInfo().use(dbInfo.getDbKey()).find(sql);
syncDbIdMap.put(dbInfo.getId(), dbInfo);
if(tableList != null && tableList.size() > 0) {
for(TableSyncInfo tableInfo : tableList) {
Long dbId = tableInfo.getDbId();
String tableName = tableInfo.getTableName();
String toKey = dbId + "#@#" + tableName;
List<SyncDbInfo> list = toFromMap.get(toKey);
if(list == null) {
list = new ArrayList<SyncDbInfo>();
toFromMap.put(toKey, list);
}
list.add(dbInfo);
}
}
}
Integer m2sInterval = PropKit.use("config.properties").getInt("syncMaterToSlaveTime",15);
Integer s2mInterval = PropKit.use("config.properties").getInt("syncSlaveToMaterTime",30);
for(Entry<String,List<SyncDbInfo>> entry : toFromMap.entrySet()) {
String toKey = entry.getKey();
String[] split = toKey.split("#@#");
Long dbId = Long.valueOf(split[0]);
String tableName = split[1];
SyncDbInfo toDb = syncDbIdMap.get(dbId);
List<SyncDbInfo> fromDb = entry.getValue();
String jobGroupName = toDb.getDbKey();
Map<String,Object> dataMap= new HashMap<String,Object>();
dataMap.put("toDb", toDb);//同步的目标数据库
dataMap.put("fromDb", fromDb);//从哪几个库同步
dataMap.put("tableName", tableName);//同步的表名
boolean master = toDb.isMaster();//是否是主库
Integer jobInterval = master ? s2mInterval : m2sInterval;
QuartzUtils.addJob(SCHEDULER, SyncDataJob.class, jobInterval, tableName, jobGroupName, tableName, jobGroupName, dataMap);
logger.info(String.format("同步定时任务添加成功toDb: %s ,toDbIsMaster: %s ,fromDbSize: %s ,interval: %ss,tableName: %s ", toDb.getDbKey(),toDb.isMaster(), fromDb.size(),jobInterval, tableName));
}
SCHEDULER.start();
}
//初始化多数据源数据库连接
public static void createConn(List<SyncDbInfo> syncDbInfos){
logger.info("开始创建各分库数据库的连接池");
PropKit.use("db.properties");
for (SyncDbInfo syncDbInfo : syncDbInfos) {
String url="jdbc:mysql://"+syncDbInfo.get("ip")+":"+syncDbInfo.get("port")+"/"+syncDbInfo.get("database_name")+"?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true&rewriteBatchedStatements=true";
//初始化各数据源插件
DruidPlugin druid=new DruidPlugin(url,(String)syncDbInfo.get("user"),(String)syncDbInfo.get("password"));
druid.setInitialSize(Integer.valueOf(PropKit.get("dbInitialSize")));
druid.setMaxActive(Integer.valueOf(PropKit.get("dbMaxActive")));
druid.setMinIdle(Integer.valueOf(PropKit.get("dbMinIdle")));
druid.setMaxWait(Integer.valueOf(PropKit.get("dbMaxWait")));
druid.setRemoveAbandoned(Boolean.valueOf(PropKit.get("dbRemoveAbandoned")));
druid.setRemoveAbandonedTimeoutMillis(Integer.valueOf(PropKit.get("dbRemoveAbandonedTimeout")));
druid.setConnectionProperties(SyncData.DRUID_CONFIG_FILE_PATH);//druid 配置文件路径
ActiveRecordPlugin arp=new ActiveRecordPlugin(syncDbInfo.getDbKey(),druid);
arp.setShowSql(Boolean.valueOf(PropKit.get("dbShowSql")));
druid.start();
arp.start();
logger.info(String.format("数据源创建成功ip: %s,port: %s,database %s ", syncDbInfo.getIp(),syncDbInfo.getPort(),syncDbInfo.getDatabaseName()));
}
logger.info("创建各分库数据库的连接池完成");
}
}

View File

@@ -7,5 +7,25 @@ import com.nms.model.basemodel.BaseSyncDbInfo;
*/
@SuppressWarnings("serial")
public class SyncDbInfo extends BaseSyncDbInfo<SyncDbInfo> {
public static final SyncDbInfo dao = new SyncDbInfo().dao();
private TableSyncInfo tableInfo;
public String getDbKey() {
return this.getIp()+":"+this.getPort()+"-"+this.getDatabaseName();
}
/**
* 是否为主库
* @return
*/
public boolean isMaster() {
return this.getMaster() == 1;
}
public TableSyncInfo getTableInfo() {
return tableInfo;
}
public void setTableInfo(TableSyncInfo tableInfo) {
this.tableInfo = tableInfo;
}
}

View File

@@ -8,4 +8,22 @@ import com.nms.model.basemodel.BaseTableSyncInfo;
@SuppressWarnings("serial")
public class TableSyncInfo extends BaseTableSyncInfo<TableSyncInfo> {
public static final TableSyncInfo dao = new TableSyncInfo().dao();
public String getEventStr() {
String result = null;
Integer event = this.getEvent();
switch (event) {
case 1:
result = "insert";break;
case 2:
result = "update"; break;
case 3:
result = "delete"; break;
default:
result = "unknown"; break;
}
return result;
}
}

View File

@@ -57,4 +57,12 @@ public abstract class BaseSyncDbInfo<M extends BaseSyncDbInfo<M>> extends Model<
return getStr("password");
}
public void setMaster(java.lang.Integer master) {
set("master", master);
}
public java.lang.Integer getMaster() {
return getInt("master");
}
}

View File

@@ -17,12 +17,12 @@ public abstract class BaseTableEventLog<M extends BaseTableEventLog<M>> extends
return getLong("id");
}
public void setTable(java.lang.String table) {
set("table", table);
public void setTableName(java.lang.String tableName) {
set("table_name", tableName);
}
public java.lang.String getTable() {
return getStr("table");
public java.lang.String getTableName() {
return getStr("table_name");
}
public void setEvent(java.lang.Integer event) {
@@ -49,4 +49,12 @@ public abstract class BaseTableEventLog<M extends BaseTableEventLog<M>> extends
return getStr("ids");
}
public void setTime(java.util.Date time) {
set("time", time);
}
public java.util.Date getTime() {
return get("time");
}
}

View File

@@ -66,11 +66,11 @@ public abstract class BaseTableSyncInfo<M extends BaseTableSyncInfo<M>> extends
}
public void setLastId(java.lang.Long lastId) {
set("last_Id", lastId);
set("last_id", lastId);
}
public java.lang.Long getLastId() {
return getLong("last_Id");
return getLong("last_id");
}
public void setLastDate(java.util.Date lastDate) {
@@ -113,4 +113,21 @@ public abstract class BaseTableSyncInfo<M extends BaseTableSyncInfo<M>> extends
return getStr("interceptor");
}
public void setUpdateIds(java.lang.String updateIds) {
set("update_ids", updateIds);
}
public java.lang.String getUpdateIds() {
return getStr("update_ids");
}
public void setExcludeNames(java.lang.String excludeNames) {
set("exclude_names", excludeNames);
}
public java.lang.String getExcludeNames() {
return getStr("exclude_names");
}
}

View File

@@ -0,0 +1,297 @@
package com.nms.util;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
/**
* 定时任务调度工具类
* @author ThinkPad
*
*/
@SuppressWarnings("all")
public class QuartzUtils {
private static Logger logger = Logger.getLogger(QuartzUtils.class);
private static String JOB_NAME = "SYNC_JOB";
private static String JOB_GROUP_NAME = "SYNC_JOBGROUP";
private static String TRIGGER_NAME = "SYNC_TRIGGER";
private static String TRIGGER_GROUP_NAME = "SYNC_TRIGGERGROUP";
/**
* 创建调度器
* @param path
* @return
* @throws SchedulerException
*/
public static Scheduler createScheduler(String path) throws SchedulerException {
StdSchedulerFactory sf = new StdSchedulerFactory(path);
Scheduler scheduler = sf.getScheduler();
return scheduler;
}
public static Scheduler createScheduler(Properties config) throws SchedulerException {
StdSchedulerFactory sf = new StdSchedulerFactory(config);
Scheduler scheduler = sf.getScheduler();
return scheduler;
}
/**
* @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
* @param sched:调度器
* @param jobClass:任务
* @param time:时间设置CronExpression表达式
*/
public static void addJob(Scheduler sched, Class jobClass, String time) {
addJob(sched, jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);
}
/**
* @Description: 添加一个定时任务
* @param sched:调度器
* @param jobClass:任务
* @param time:时间设置CronExpression表达式
* @param jobName:任务名
* @param jobGroupName:任务组名
* @param triggerName:触发器名
* @param triggerGroupName:触发器组名
*/
public static void addJob(Scheduler sched, Class jobClass, String time,
String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName)
.withSchedule(CronScheduleBuilder.cronSchedule(time)).build();
try {
// 返回为 null 添加失败
Date ft = sched.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
* @param sched:调度器
* @param jobClass:任务
* @param seconds:时间设置,间隔 n s 执行一次
* @throws SchedulerException
*/
public static void addJob(Scheduler sched, Class jobClass, int seconds,Map<String,Object> dataMap) throws SchedulerException {
addJob(sched, jobClass,seconds,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME,dataMap);
}
/**
* @Description: 添加一个定时任务
* @param sched:调度器
* @param jobClass:任务
* @param seconds:时间设置,间隔 n s 执行一次
* @param jobName:任务名
* @param jobGroupName:任务组名
* @param triggerName:触发器名
* @param triggerGroupName:触发器组名
* @throws SchedulerException
*/
public static void addJob(Scheduler sched, Class jobClass, int seconds,
String jobName, String jobGroupName, String triggerName, String triggerGroupName,Map<String,Object> dataMap) throws SchedulerException {
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
if(dataMap != null) {
JobDataMap jobDataMap = job.getJobDataMap();
jobDataMap.putAll(dataMap);
}
SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName).withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(seconds)).build();
JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
boolean checkExists = sched.checkExists(jobKey);
if(checkExists) {
sched.deleteJob(jobKey);
logger.debug("任务已经存在,删除成功," + jobKey.toString());
}
// 返回为 null 添加失败
Date ft = sched.scheduleJob(job, trigger);
}
/**
* @Description: 定义一个任务之后进行触发设定(使用默认的任务组名,触发器名,触发器组名)
* @param sched:调度器
* @param time
*/
public static void addJObLaterUse(Scheduler sched, Class jobClass, String time) {
addJObLaterUse(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME);
}
/**
* @Description: 定义一个任务之后进行触发设定
* @param sched:调度器
* @param time
* @param jobName:任务名
* @param jobGroupName:任务组名
*/
public static void addJObLaterUse(Scheduler sched, Class jobClass, String time,
String jobName,String jobGroupName) {
JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).storeDurably().build();
try {
sched.addJob(job, false);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 对已存储的任务进行scheduling(使用默认的任务组名,触发器名,触发器组名)
* @param sched:调度器
* @param time
* @param jobName:任务名
* @param jobGroupName:任务组名
*/
public static void schedulingStoredJOb(Scheduler sched, Class jobClass, String time) {
schedulingStoredJOb(sched,jobClass,time,JOB_NAME,JOB_GROUP_NAME,TRIGGER_NAME,TRIGGER_GROUP_NAME);
}
/**
* @Description: 对已存储的任务进行scheduling
* @param sched:调度器
* @param time
* @param jobName:任务名
* @param jobGroupName:任务组名
*/
public static void schedulingStoredJOb(Scheduler sched, Class jobClass, String time,
String jobName,String jobGroupName,String triggerName, String triggerGroupName) {
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName).startNow()
.forJob(JobKey.jobKey(jobName,jobGroupName))
.build();
try {
sched.scheduleJob(trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
* @param sched:调度器
* @param time
*/
public static void modifyJobTime(Scheduler sched, String time) {
modifyJobTime(sched, TRIGGER_NAME, TRIGGER_GROUP_NAME, time);
}
/**
* @Description: 修改一个任务的触发时间
* @param sched:调度器
* @param triggerName
* @param triggerGroupName
* @param time
*/
public static void modifyJobTime(Scheduler sched, String triggerName, String triggerGroupName, String time) {
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(triggerName, triggerGroupName).withSchedule(CronScheduleBuilder.cronSchedule(time)).startNow().build();
try {
sched.rescheduleJob(TriggerKey.triggerKey(triggerName, triggerGroupName), trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 修改一个任务(使用默认的任务组名,任务名)
* @param sched:调度器
*/
public static void modifyJob(Scheduler sched, Class jobClass) {
modifyJob(sched,jobClass,JOB_NAME,JOB_GROUP_NAME);
}
/**
* @Description: 修改一个任务
* @param sched:调度器
* @param jobName:任务名
* @param jobGroupName:任务组名
*/
public static void modifyJob(Scheduler sched, Class jobClass, String jobName,String jobGroupName) {
JobDetail job1 = JobBuilder.newJob(jobClass).withIdentity(jobName,jobGroupName).build();
try {
sched.addJob(job1, true);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 删除一个任务的的trigger
* @param sched:调度器
* @param triggerName
* @param triggerGroupName
*/
public static void unschedulingJob(Scheduler sched,String triggerName, String triggerGroupName) {
try {
sched.unscheduleJob(TriggerKey.triggerKey(triggerName,triggerGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description: 移除一个任务以及任务的所有trigger
* @param sched:调度器
* @param jobName
*/
public static void removeJob(Scheduler sched, String jobName,String jobGroupName) {
try {
sched.deleteJob(JobKey.jobKey(jobName,jobGroupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* @Description:启动所有定时任务
* @param sched:调度器
*/
public static void startJobs(Scheduler sched) {
try {
sched.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:关闭所有定时任务
* @param sched:调度器
*/
public static void shutdownJobs(Scheduler sched) {
try {
if (!sched.isShutdown()) {
//未传参或false不等待执行完成便结束true等待任务执行完才结束
sched.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,165 @@
package com.nms.util;
import org.apache.log4j.Logger;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.nms.model.TableSyncInfo;
/**
* 公共方法,变量
* @author fang
*
*/
public class SyncCommon {
private static final Logger logger = Logger.getLogger(SyncCommon.class);
public static final String TABLE_NAME_ALIAS;//表别名
static {
Prop config = PropKit.use("config.properties");
TABLE_NAME_ALIAS = config.get("table.alias.name", "t_alias");
}
/**
* insert mode = 2 时的select 语句,不关联 table_event_log
* @param tableName
* @param tableInfo
* @param idName
* @param columns
* @param where
* @return
*/
public static StringBuilder insertModeTwoSql( TableSyncInfo tableInfo) {
String tableName = tableInfo.getTableName();
String idName = tableInfo.getIdName();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
StringBuilder sbSql = new StringBuilder("select ");
sbSql.append(getColums(columns, null)).append(" from ").append(tableName).append(" ").append(SyncCommon.TABLE_NAME_ALIAS).append(" where ").append(idName).append(" > ? ");
if(StrKit.notBlank(where)) {
sbSql.append(" and ( ").append(where).append(" )");
}
sbSql.append(" order by ").append(tableInfo.getIdName()).append(" asc limit ? ");
return sbSql;
}
/**
* 关联 table_event_log 表 获取 表变更记录
* @param tableInfo
* @return
*/
public static StringBuilder getSelectSqlLeftJoinEventLog(TableSyncInfo tableInfo) {
String tableName = tableInfo.getTableName();
String idName = tableInfo.getIdName();
String columns = tableInfo.getColumns();
String where = tableInfo.getWhere();
Integer event = tableInfo.getEvent();
Integer mode = tableInfo.getMode();
StringBuilder sbSql = new StringBuilder();
String colums = getColums(columns, TABLE_NAME_ALIAS);
if(event == 2 && mode == 1 && ! columns.contains("*")) {//查询更新记录时 group by 找到符合条件最后一条记录
sbSql.append("select ").append(colums).append(",max(log.id) as tableeventlogid").append(" from ").append(tableName).append(" ").append(TABLE_NAME_ALIAS)
.append(" left join table_event_log log on log.target_id = ").append(TABLE_NAME_ALIAS).append(".").append(idName)
.append(" where ").append(" log.id ").append(" > ? ").append(" and log.table_name= '").append(tableInfo.getTableName()).append("' and log.event = ").append(event);
if(StrKit.notBlank(where)) {
sbSql.append(" and ( ").append(where).append(" )");
}
sbSql.append(" group by ").append(columns);
sbSql.append(" order by ").append(" log.id ").append(" asc limit ? ");
}else {
sbSql.append("select ").append(getColums(columns, TABLE_NAME_ALIAS)).append(",log.id as tableeventlogid").append(" from ").append(tableName).append(" ").append(TABLE_NAME_ALIAS)
.append(" left join table_event_log log on log.target_id = ").append(TABLE_NAME_ALIAS).append(".").append(idName)
.append(" where ").append(" log.id ").append(" > ? ").append(" and log.table_name= '").append(tableInfo.getTableName()).append("' and log.event = ").append(event);
if(StrKit.notBlank(where)) {
sbSql.append(" and ( ").append(where).append(" )");
}
sbSql.append(" order by ").append(" log.id ").append(" asc limit ? ");
}
logger.debug(String.format("sql -> %s", sbSql.toString()));
return sbSql;
}
/**
* event = 3 delete 同步查询记录语句,关联 table_event_log
* @param tableName
* @param tableInfo
* @param idName
* @param columns
* @param where
* @return
*/
public static StringBuilder delSelectLeftJoinEventLog(TableSyncInfo tableInfo) {
String idName = tableInfo.getIdName();
StringBuilder sbSql = new StringBuilder("select id as tableeventlogid,target_id as ");
sbSql.append(idName).append(" from table_event_log log")
.append(" where ").append(" log.id ").append(" > ? ").append(" and log.table_name= '").append(tableInfo.getTableName()).append("' and log.event = ").append(tableInfo.getEvent());
sbSql.append(" order by ").append(" log.id ").append(" asc limit ? ");
logger.debug(String.format("sql -> %s", sbSql.toString()));
return sbSql;
}
/**
* 获取查询字段
* @param columns
* @param alias 表别名
* @return
*/
public static String getColums(String columns,String alias) {
if(StrKit.notBlank(columns)) {//
StringBuffer sb = new StringBuffer();
String[] split = columns.split(",");
for(String s : split) {
if(StrKit.notBlank(s)) {
sb.append(",");
if(StrKit.notBlank(alias)) {
sb.append(alias);
sb.append(".");
}
sb.append(s);
}
}
if(sb.length()>0) {
sb.deleteCharAt(0);
sb.insert(0, " ");
sb.append(" ");
return sb.toString();
}
}
return StrKit.isBlank(alias)?" * " : " " +alias +".* ";
}
/**
* 生成 delete sql 语句
* @param tableName
* @param updateIds
* @return
*/
public static String genDelSql(String tableName,String updateIds,String where) {
StringBuilder sb = new StringBuilder(" delete from ");
sb.append(tableName).append(" where ");
String[] split = updateIds.split(",");
StringBuilder whereSb = new StringBuilder();
for(String s : split) {
if(StrKit.notBlank(s)) {
whereSb.append("and ").append(s).append(" =? ");
}
}
if(StrKit.notBlank(where)) {
whereSb.append(" and ( ").append(where).append(" )");
}
if(whereSb.length() > 0) {
whereSb.delete(0, 3);
}
sb.append(whereSb.toString());
return sb.toString();
}
}