SYSDATE в операторах JDBC, похоже, возвращает разное время при запросе к одной и той же базе данных Oracle - PullRequest
0 голосов
/ 06 октября 2018

У нас есть от 3 до 4 сред с одинаковой настройкой, каждая из которых имеет несколько кластерных серверов приложений (WebSphere) и базы данных Oracle Supercluster.

Проблема, которую я вижу, кажется, происходит только в одной из сред, которая тоже примерно в 20% случаев .

У нас

  • Два приложения развернуты в одном и том же кластере серверов приложений

  • Оба приложения используют один и тот же источник данных, настроенный для использования базы данных Oracle, которая является суперскластером Oracle.

Ниже приведена структура рассматриваемой таблицы

TABLE SESSION_TBL 
(
    ID NUMBER(12, 0) NOT NULL, 
    USER_ID VARCHAR2(256 BYTE) NOT NULL, 
    SESSION_ID VARCHAR2(60 BYTE) NOT NULL, 
    LOGIN_TIME TIMESTAMP(6) NOT NULL 
 ) 

Приложение 1 сохраняет запись с использованием JDBC

    String sql = "Insert into SESSION_TBL " +
                 "  (USER_ID, SESSION_ID, LOGIN_TIME ) " +
                 "  values (?,?,SYSDATE)";

    try
    {
        sessionId = getNewSessionId(userId);
        st = conn.prepareStatement(sql);
        st.setString(1, userId);
        st.setString(2, sessionId);
        int rows = st.executeUpdate();
    }

Через несколько секунд Приложение 2 выполняетследующий код для поиска записи, вставленной первым приложением, и сравнение с текущим временем

Statement st = null;
ResultSet result = null;

String sql = " Select * " +
" from SESSION_TBL " +
" where USER_ID = '" + userId + "' " +
" and SESSION_ID = '" + sessionId + "' ";

try {
    st = conn.createStatement();
    result = st.executeQuery(sql);

    if(!result.next()) { // We have no data, need to expire the session
        logger.debug("End hasSessionExpired()");
        return true;
    }
    else {
         logger.debug("SessionInfo:ResultSet not null");
    }


    // Get the time user logged in
    // java.sql.Timestamp
    Timestamp database_date = result.getTimestamp("LOGIN_TIME"); // get date from db
    long databaseDate = database_date.getTime(); // Convert to UNIX time

    // Get the current time from the database, so we are getting the time
    // from the same sources to compare
    // See the code below for this function
    long currentTime = getCurrentTimeFromDB (conn);

    // Both time values would be in milli seconds
    long diffSecs = (currentTime - databaseDate)/1000; 
    logger.info ("db:" + databaseDate + "   now:" + currentTime + " diffSecs:" + diffSecs);

код для получения текущего времени из базы данных

public static long getCurrentTimeFromDB () {
   .
   .
    // Using SYSDATE.  We only need precision upto seconds
    String s = "SELECT SYSDATE NOW FROM DUAL";
    rs = statement.executeQuery(s);
    if (rs.next()) {
        Timestamp dbTime = rs.getTimestamp("NOW");
        currentTime = dbTime.getTime();
    }
    return currentTime;
}

примерно в 1 из 5или около того выполнения, я вижу текущее время на раньше , чем время создания записи (время входа в систему).Когда это происходит, я вижу вывод оператора отладки, подобный следующему:

db:1538793249000   now:1538793023000 diffSecs:-226
db:1538793249000   now:1538793023000 diffSecs:-202
db:1538793249000   now:1538793023000 diffSecs:-225

Похоже, примерно на 200+ секунд раньше

Если вы заметили одну вещь, тип данных столбца (LOGIN_TIME) является меткой времени, и я использую SYSDATE для ее заполнения.Тем не менее, я также использую SYSDATE, чтобы получить время от ДВОЙНОГО.Из 4-х сред, которые мы имеем, это происходит в одной и не всегда.Что-то не так в коде или возможно, что супер-кластер базы данных Oracle) на самом деле возвращает неправильную дату.

1 Ответ

0 голосов
/ 30 октября 2018

Я думал, что поставлю ответ, если кто-то столкнется с подобной проблемой.Как и предполагали (в комментариях), время узлов кластера может быть не синхронизировано.У нас есть 2 узла в кластере, один узел опередил (текущего времени) на пару минут.Можно определить, не синхронизировано ли время, запустив запрос SYSDATE для каждого узла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...