Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

Commit

Permalink
bugfix: fix the full table scan issue with 'setDate' condition in Ora…
Browse files Browse the repository at this point in the history
…cle 10g (apache#5498)
  • Loading branch information
slievrly committed Apr 13, 2023
1 parent 08fd84b commit 9b35ba9
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 23 deletions.
82 changes: 82 additions & 0 deletions common/src/main/java/io/seata/common/util/DateUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.seata.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
* The type Date util.
*
* @author slievrly
*/
public class DateUtil {

/**
* Gets current date.
*
* @return the current date
*/
public static Date getCurrentDate() {
return new Date();
}

/**
* Parse date date.
*
* @param dateStr the date str
* @param format the format
* @return the date
* @throws ParseException the parse exception
*/
public static Date parseDate(String dateStr, String format) throws ParseException {
if (StringUtils.isBlank(dateStr)) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.parse(dateStr);
}

public static Date parseDateWithoutTime(String dateStr) throws ParseException {
return parseDate(dateStr, "yyyy-MM-dd");
}

public static Date getDateNowPlusDays(int days) throws ParseException {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, days);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = dateFormat.format(calendar.getTime());
return dateFormat.parse(dateStr);
}

/**
* Format date string.
*
* @param date the date
* @param format the format
* @return the string
*/
public static String formatDate(Date date, String format) {
if (date == null) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(format);
return sdf.format(date);
}
}
57 changes: 57 additions & 0 deletions common/src/test/java/io/seata/common/util/DateUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 1999-2019 Seata.io Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.seata.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

/**
* @author slievrly
*/
public class DateUtilTest {
@Test
public void testGetCurrentDate() {
Date currentDate = DateUtil.getCurrentDate();
Assertions.assertNotNull(currentDate);
}

@Test
public void testParseDate() throws ParseException {
String dateStr = "2021-01-01";
Date date = DateUtil.parseDate(dateStr, "yyyy-MM-dd");
Assertions.assertNotNull(date);

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Assertions.assertEquals(dateStr, sdf.format(date));
}

@Test
public void testFormatDate() {
Date currentDate = DateUtil.getCurrentDate();
String dateStr = DateUtil.formatDate(currentDate, "yyyy-MM-dd HH:mm:ss");
Assertions.assertNotNull(dateStr);
}

@Test
public void testGetDateNowPlusDays() throws ParseException {
Assertions.assertNotNull(DateUtil.getDateNowPlusDays(2));
}
}
17 changes: 10 additions & 7 deletions rm-datasource/src/main/java/io/seata/rm/RMHandlerAT.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Calendar;
import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import io.seata.common.util.DateUtil;
import io.seata.core.model.BranchType;
import io.seata.core.model.ResourceManager;
import io.seata.core.protocol.transaction.UndoLogDeleteRequest;
Expand Down Expand Up @@ -126,13 +127,15 @@ int deleteUndoLog(UndoLogManager manager, Connection conn, Date division) {
}
}

private Date getLogCreated(int saveDays) {
if (saveDays <= 0) {
saveDays = UndoLogDeleteRequest.DEFAULT_SAVE_DAYS;
private Date getLogCreated(int pastDays) {
if (pastDays <= 0) {
pastDays = UndoLogDeleteRequest.DEFAULT_SAVE_DAYS;
}
try {
return DateUtil.getDateNowPlusDays(-pastDays);
} catch (ParseException exx) {
throw new RuntimeException(exx);
}
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -saveDays);
return calendar.getTime();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package io.seata.rm.datasource.undo.oracle;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;

import io.seata.common.loader.LoadLevel;
import io.seata.common.util.DateUtil;
import io.seata.core.compressor.CompressorType;
import io.seata.core.constants.ClientTableColumnsName;
import io.seata.rm.datasource.undo.AbstractUndoLogManager;
Expand All @@ -47,13 +47,13 @@ public class OracleUndoLogManager extends AbstractUndoLogManager {
+ ClientTableColumnsName.UNDO_LOG_LOG_CREATED + ", " + ClientTableColumnsName.UNDO_LOG_LOG_MODIFIED + ")"
+ "VALUES (UNDO_LOG_SEQ.nextval, ?, ?, ?, ?, ?, sysdate, sysdate)";

private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME +
" WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= ? and ROWNUM <= ?";
private static final String DELETE_UNDO_LOG_BY_CREATE_SQL = "DELETE FROM " + UNDO_LOG_TABLE_NAME + " WHERE " + ClientTableColumnsName.UNDO_LOG_LOG_CREATED + " <= to_date(?,'yyyy-mm-dd hh24:mi:ss') and ROWNUM <= ?";

@Override
public int deleteUndoLogByLogCreated(Date logCreated, int limitRows, Connection conn) throws SQLException {
try (PreparedStatement deletePST = conn.prepareStatement(DELETE_UNDO_LOG_BY_CREATE_SQL)) {
deletePST.setDate(1, new java.sql.Date(logCreated.getTime()));
String dateStr = DateUtil.formatDate(logCreated, "yyyy-MM-dd HH:mm:ss");
deletePST.setString(1, dateStr);
deletePST.setInt(2, limitRows);
int deleteRows = deletePST.executeUpdate();
if (LOGGER.isDebugEnabled()) {
Expand Down
5 changes: 2 additions & 3 deletions script/client/at/db/mysql.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@ CREATE TABLE IF NOT EXISTS `undo_log`
`log_created` DATETIME(6) NOT NULL COMMENT 'create datetime',
`log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime',
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
AUTO_INCREMENT = 1
DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
14 changes: 8 additions & 6 deletions script/client/at/db/oracle.sql
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE undo_log
(
id NUMBER(19) NOT NULL,
branch_id NUMBER(19) NOT NULL,
xid VARCHAR2(128) NOT NULL,
context VARCHAR2(128) NOT NULL,
rollback_info BLOB NOT NULL,
log_status NUMBER(10) NOT NULL,
log_created TIMESTAMP(0) NOT NULL,
log_modified TIMESTAMP(0) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT ux_undo_log UNIQUE (xid, branch_id)
);

CREATE INDEX ix_log_created ON undo_log(log_created);
COMMENT ON TABLE undo_log IS 'AT transaction mode undo table';

-- Generate ID using sequence and trigger
CREATE SEQUENCE UNDO_LOG_SEQ START WITH 1 INCREMENT BY 1;
COMMENT ON COLUMN undo_log.branch_id is 'branch transaction id';
COMMENT ON COLUMN undo_log.xid is 'global transaction id';
COMMENT ON COLUMN undo_log.context is 'undo_log context,such as serialization';
COMMENT ON COLUMN undo_log.rollback_info is 'rollback info';
COMMENT ON COLUMN undo_log.log_status is '0:normal status,1:defense status';
COMMENT ON COLUMN undo_log.log_created is 'create datetime';
COMMENT ON COLUMN undo_log.log_modified is 'modify datetime';
12 changes: 9 additions & 3 deletions script/client/at/db/postgresql.sql
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
-- for AT mode you must to init this sql for you business database. the seata server not need it.
CREATE TABLE IF NOT EXISTS public.undo_log
(
id SERIAL NOT NULL,
branch_id BIGINT NOT NULL,
xid VARCHAR(128) NOT NULL,
context VARCHAR(128) NOT NULL,
rollback_info BYTEA NOT NULL,
log_status INT NOT NULL,
log_created TIMESTAMP(0) NOT NULL,
log_modified TIMESTAMP(0) NOT NULL,
CONSTRAINT pk_undo_log PRIMARY KEY (id),
CONSTRAINT ux_undo_log UNIQUE (xid, branch_id)
);
CREATE INDEX ix_log_created ON undo_log(log_created);

CREATE SEQUENCE IF NOT EXISTS undo_log_id_seq INCREMENT BY 1 MINVALUE 1 ;
COMMENT ON TABLE public.undo_log IS 'AT transaction mode undo table';
COMMENT ON COLUMN public.undo_log.branch_id IS 'branch transaction id';
COMMENT ON COLUMN public.undo_log.xid IS 'global transaction id';
COMMENT ON COLUMN public.undo_log.context IS 'undo_log context,such as serialization';
COMMENT ON COLUMN public.undo_log.rollback_info IS 'rollback info';
COMMENT ON COLUMN public.undo_log.log_status IS '0:normal status,1:defense status';
COMMENT ON COLUMN public.undo_log.log_created IS 'create datetime';
COMMENT ON COLUMN public.undo_log.log_modified IS 'modify datetime';

0 comments on commit 9b35ba9

Please sign in to comment.