Какой эффективный способ найти строки, где метка времени и идентичность не в последовательности? - PullRequest
2 голосов
/ 30 января 2010

Справочная информация:

У меня есть приложение MS SQL, которое считывает данные из нашей биллинговой базы данных Oracle один раз в час в поисках новых платежей. Это достигается путем сохранения временной метки на основе CRT_DTTM самой последней временной метки, найденной при каждом запуске.

, например

SELECT *
FROM V_TRANS
WHERE TRANS_CLS = 'P'
AND CRT_DTTM > TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS')

После возвращения этого результата MAX(CRT_DTTM) сохраняется в качестве начальной отметки времени для следующего часового прогона.

Кажется, что происходит то, что иногда на стороне Oracle выполняется транзакция, которая вставляет данные в таблицу одновременно с выполнением моего запроса. Строки, по-видимому, не вставляются в порядке полученной метки времени. Это означает, что мой MAX(CRT_DTTM) больше, чем некоторые строки, которые вставляются после завершения моего запроса. Я пропустил платежную информацию, и мои системы вышли из баланса.

Я считаю, что могу обойти это, просто изменив мой оператор SQL выше, добавив:

...
AND CRT_DTTM < SYSDATE - INTERVAL '10' MINUTE

Вопрос:

Я хочу знать, есть ли способ проверить строки, уже вставленные в таблицу, чтобы найти те карманы, в которых идентичность не совпадает с отметкой времени:

database sequence vs timestamp

Я хочу найти карманы данных в этой ситуации, чтобы узнать, достаточно ли 10 минут, чтобы задержать просмотр метки времени.

SELECT *
FROM V_TRANS t1
JOIN V_TRANS t2
    ON t1.trans_id < t2.trans_id
        AND t2.crt_dttm < t1.crt_dttm
WHERE t1.TRANS_CLS = 'P'
    AND t1.CRT_DTTM > TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS')
    -- Only look at an interval of one day
    AND t1.CRT_DTTM < TO_DATE('2010-01-25 12:59:44', 'YYYY-MM-DD HH24-MI-SS') + 1

Или, может быть, я пропускаю некоторые базовые настройки уровня изоляции транзакций? Я запускаю это через связанный сервер с OPENQUERY()

Ответы [ 3 ]

2 голосов
/ 30 января 2010
SELECT
  *
FROM (
        SELECT
          t1.*,
          RANK() OVER (ORDER BY trans_id) AS trans_id_rank,
          -- Ordering by trans_id after CRT_DTTM to cater for transactions within the same second
          RANK() OVER (ORDER BY CRT_DTTM, trans_id) AS CRT_DTTM_rank
        FROM V_TRANS t1) t
WHERE trans_id_rank <> CRT_DTTM_rank
1 голос
/ 30 января 2010

"По-видимому, строки не вставляются в порядке полученной метки времени. Скорее всего, они не являются COMMITED в порядке меток времени, поэтому они были вставлены, но не зафиксированы при выполнении запроса.

Посмотрите, предоставит ли вам администратор базы данных Oracle гранты на V $ TRANSACTION.Затем вы можете увидеть время начала любых открытых транзакций, как долго они открыты и т. Д. Также, если база данных Oracle имеет RAC, очень вероятно, что порядковые номера (ближайший Oracle имеет идентичные столбцы) тоже не в порядке.,Каждый узел в RAC имеет свой собственный кэш для уменьшения конкуренции.

В 11gR2 они ввели WAITING_ON_PENDING_DML для обслуживания этой ситуации.

0 голосов
/ 30 января 2010
select t1.id, t2.id, t1.timestamp - t2.timestamp
from table t1
join table t2 on t1.id = t2.id - 1
where t1.timestamp < t2.timestamp

EDIT:

Я написал этот ответ, затем понял, что это более или менее тот же запрос, который у вас уже был. Поэтому я не должен понимать ваш вопрос.

Мой запрос будет "... проверять строки, уже вставленные в таблицу, чтобы найти те карманы, в которых идентичность не совпадает с отметкой времени", как я думал, был вашим вопросом.

Кстати, если вы просто ищете, какой самый большой скачок назад отметки времени, вы можете использовать:

select max(t2.timestamp - t1.timestamp)
from table t1
join table t2 on t1.id = t2.id - 1;

Если я неправильно понимаю ваш вопрос, пожалуйста, дайте мне знать, что мне не хватает.

...