@@ -81,8 +81,6 @@ public class LogMinerConnection {
8181 public boolean isGBK = false ;
8282 boolean isOracle10 ;
8383
84- public static final long MAX_SCN = 281474976710655L ;
85-
8684 public static final List <String > PRIVILEGES_NEEDED = Arrays .asList (
8785 "CREATE SESSION" ,
8886 "LOGMINING" ,
@@ -249,37 +247,26 @@ public void startOrUpdateLogMiner(BigDecimal startScn) {
249247 if (logMinerConfig .getSupportAutoAddLog ()) {
250248 startSql = isOracle10 ? SqlUtil .SQL_START_LOG_MINER_AUTO_ADD_LOG_10 : SqlUtil .SQL_START_LOG_MINER_AUTO_ADD_LOG ;
251249 } else {
252- //第一次加载或者已经没有归档日志加载 只有online日志加载 此时maxScn为空
250+ //第一次加载, 此时maxScn为空
253251 if (null == maxScn ) {
254- if (null != minScn && startScn .compareTo (minScn ) < 0 ) {
255- maxScn = minScn ;
256- } else {
257- maxScn = startScn ;
258- }
252+ maxScn = startScn ;
259253 }
260254
261255 List <LogFile > newLogFiles = queryLogFiles (maxScn );
262256 if (addedLogFiles .equals (newLogFiles )) {
263257 return ;
264258 } else {
265- // LOG.info("Log group changed, new log group = {}", GsonUtil.GSON.toJson(newLogFiles));
266259 addedLogFiles = newLogFiles ;
267- // startSql = isOracle10 ? SqlUtil.SQL_START_LOG_MINER_10 : SqlUtil.SQL_START_LOG_MINER;
268- startSql = null == maxScn ? SqlUtil .SQL_START_LOGMINER_NO_MAX_LIMIT : SqlUtil .SQL_START_LOGMINER_HAS_MAX_LIMIT ;
260+ startSql = SqlUtil .SQL_START_LOGMINER ;
269261 }
270262 }
271263
272- closeStmt (logMinerStartStmt );
273-
274- logMinerStartStmt = connection .prepareCall (startSql );
275- configStatement (logMinerStartStmt );
264+ resetLogminerStmt (startSql );
276265 if (logMinerConfig .getSupportAutoAddLog ()) {
277266 logMinerStartStmt .setBigDecimal (1 , startScn );
278267 } else {
279268 logMinerStartStmt .setBigDecimal (1 , minScn );
280- if (null != maxScn ) {
281- logMinerStartStmt .setBigDecimal (2 , maxScn );
282- }
269+ logMinerStartStmt .setBigDecimal (2 , maxScn );
283270 }
284271
285272 logMinerStartStmt .execute ();
@@ -294,12 +281,8 @@ public void startOrUpdateLogMiner(BigDecimal startScn) {
294281 }
295282 }
296283
297-
298284 public void startOrUpdateLogminer (BigDecimal startScn , BigDecimal endScn ) throws SQLException {
299- closeStmt (logMinerStartStmt );
300-
301- logMinerStartStmt = connection .prepareCall (SqlUtil .SQL_START_LOGMINER_HAS_MAX_LIMIT );
302- configStatement (logMinerStartStmt );
285+ resetLogminerStmt (SqlUtil .SQL_START_LOGMINER );
303286
304287 logMinerStartStmt .setBigDecimal (1 , startScn );
305288 logMinerStartStmt .setBigDecimal (2 , endScn );
@@ -316,17 +299,12 @@ public void startOrUpdateLogminer(BigDecimal startScn, BigDecimal endScn) throws
316299 */
317300 public void queryData (BigDecimal startScn , String logMinerSelectSql ) {
318301 try {
319- if (null != maxScn ) {
320- logMinerSelectSql += "AND scn < ?" ;
321- }
322302 logMinerSelectStmt = connection .prepareStatement (logMinerSelectSql , ResultSet .TYPE_FORWARD_ONLY , ResultSet .CONCUR_READ_ONLY );
323303 configStatement (logMinerSelectStmt );
324304
325305 logMinerSelectStmt .setFetchSize (logMinerConfig .getFetchSize ());
326306 logMinerSelectStmt .setBigDecimal (1 , startScn );
327- if (null != maxScn ) {
328- logMinerSelectStmt .setBigDecimal (2 , maxScn );
329- }
307+ logMinerSelectStmt .setBigDecimal (2 , maxScn );
330308 logMinerData = logMinerSelectStmt .executeQuery ();
331309
332310 LOG .debug ("query Log miner data, offset:{}" , startScn );
@@ -606,7 +584,7 @@ private List<LogFile> queryLogFiles(BigDecimal scn) throws SQLException {
606584 if (CollectionUtils .isEmpty (tempList )) {
607585 break ;
608586 }
609- //找到最小的firstSCN和最小的nextSCN 需要排除掉线上日志
587+ //找到最小的firstSCN和最小的nextSCN
610588 BigDecimal minFirstScn = tempList .stream ().sorted (Comparator .comparing (LogFile ::getFirstChange )).collect (Collectors .toList ()).get (0 ).getFirstChange ();
611589 BigDecimal minNextScn = tempList .stream ().sorted (Comparator .comparing (LogFile ::getNextChange )).collect (Collectors .toList ()).get (0 ).getNextChange ();
612590
@@ -624,7 +602,8 @@ private List<LogFile> queryLogFiles(BigDecimal scn) throws SQLException {
624602 }
625603 //如果最小的nextScn都是onlineNextChange,就代表加载所有的日志文件
626604 if (tempMinNextScn .equals (onlineNextChange )) {
627- tempMinNextScn = null ;
605+ //解决logminer偶尔丢失数据问题,读取online日志的时候,需要将endScn置为当前SCN
606+ tempMinNextScn = getCurrentScn ();
628607 logFiles = logFileLists ;
629608 }
630609 maxScn = tempMinNextScn ;
@@ -647,8 +626,8 @@ private List<LogFile> queryAddedLogFiles() throws SQLException {
647626 logFile .setNextChange (rs .getBigDecimal ("next_scn" ));
648627 logFile .setThread (rs .getLong ("thread_id" ));
649628 logFile .setBytes (rs .getLong ("filesize" ));
650- logFile .setStatus (rs .getInt ("STATUS " ));
651- logFile .setType (rs .getString ("TYPE " ));
629+ logFile .setStatus (rs .getInt ("status " ));
630+ logFile .setType (rs .getString ("type " ));
652631 logFileLists .add (logFile );
653632 }
654633 }
@@ -995,19 +974,6 @@ public RecordLog recursionQueryDataForRollback(RecordLog rollbackRecord) throws
995974 queryDataForRollbackConnection .connect ();
996975 }
997976
998- //不需要每次拉起一个新的queryDataForRollbackConnection 只需要移除加载的日志文件即可 (status为4的 其实是logminer提示缺少日志文件) https://docs.oracle.com/cd/B12037_01/server.101/b10755/dynviews_1132.htm
999- List <LogFile > files = queryDataForRollbackConnection .queryAddedLogFiles ().stream ().filter (i -> i .getStatus () != 4 ).collect (Collectors .toList ());
1000- if (CollectionUtils .isNotEmpty (files )){
1001- for (LogFile file : files ) {
1002- try {
1003- removeLogFile (file .getFileName ());
1004- }catch (SQLException e ){
1005- queryDataForRollbackConnection .disConnect ();
1006- queryDataForRollbackConnection .connect ();
1007- }
1008- }
1009- }
1010-
1011977 //查找出当前加载归档日志文件里的最小scn 递归查找此scn之前的文件
1012978 List <LogFile > logFiles = queryAddedLogFiles ().stream ().filter (i ->i .getStatus () != 4 && i .getType ().equalsIgnoreCase (LOG_TYPE_ARCHIVED )).collect (Collectors .toList ());
1013979
@@ -1037,11 +1003,15 @@ public RecordLog recursionQueryDataForRollback(RecordLog rollbackRecord) throws
10371003 return null ;
10381004 }
10391005
1040- public void removeLogFile (String fileName ) throws SQLException {
1041- try (PreparedStatement statement = connection .prepareStatement (SqlUtil .SQL_REMOVE_ADDED_LOG )) {
1042- statement .setString (1 ,fileName );
1043- statement .execute ();
1044- }
1006+ /**
1007+ * 重置 启动logminer的statement
1008+ * @param startSql
1009+ * @throws SQLException
1010+ */
1011+ public void resetLogminerStmt (String startSql ) throws SQLException {
1012+ closeStmt (logMinerStartStmt );
1013+ logMinerStartStmt = connection .prepareCall (startSql );
1014+ configStatement (logMinerStartStmt );
10451015 }
10461016
10471017 public enum ReadPosition {
0 commit comments