Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Возможно, конечно, вопрос и для форума "Проектирование БД", но для начала отпишусь в "родном" форуме Ниже описывается прототип схемы хранения истории изменения объекта и проблема, которая скоро съест мой мозг Хочется услышать мнения умных людей по поводу структуры хранения данных (таблиц и полей), и запросов к этим структурам. А так же варианты реализации задачи :) Имеется таблица, в которой хранится история изменения значения объекта Код: plaintext 1. 2. 3. 4. 5. Есть функции: 1) get_object_value(int object_id) - получить значение объекта на время транзакции 2) set_object_value(int object_id, varchar value) - записать значение объекта на время транзакции Есть так же большая обработка данных, которая выполняется (долго) в одной транзакции Код: plaintext 1. 2. 3. 4. 5. Проблема в том, значение объекта 100, полученное в строке "1", может отличаться от значения полученного в строке "2", так как параллельно работают другие транзакции, которые могут изменить значение объекта 100. Доп. условие задачи: Если внутри нашей транзакции у объекта изменилось значение, то при следующем вызове get_object_value должно возвратиться новое измененное значение. Изменения значения объекта в параллельных транзакциях не должны влиять на возврат функции get_object_value. Пример. Код: plaintext 1. 2. 3. 4. внутри функции get_object_value делается простой запрос (к примеру) Код: plaintext внутри функции set_object_value так же делается запрос (к примеру) Код: plaintext Этих двух запросов хватает почти для всех случаев. Вот один из случаев, для которых запросы не срабатывают Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 18:14 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan BlackЕсть огромное желание, чтобы при втором вызове get_object_value возвращалось то же значение, что и при первом вызове или измененное значение, но измененное в той же транзакции.имхо по хорошему, что бы другие транзакции не мешались - нужно соответственно усиливать изоляцию транзакций %) но тогда придётся менять логику клиента, что бы он был готов перезапускать транзакцию которая отменилась из-за нарушения изоляции. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 18:27 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
ЁшКак и хочется избежать блокировок, оставшись на уровне изоляции Read Commited ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 18:30 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
по идеи задача сводится к "выбрать из object_history последнюю запись с сортировкой по ctime у которой ttime = now() [текущая транзакция], если такой нет, выбрать просто последнюю запись с сортировкой по ctime" но остаётся проблема, если объект в текущей транзакции не изменялся, а в соседних - изменялся, тогда будет возвращён изменённый в соседней транзакции объект. можно запоминать состояние объекта на начало транзакции (но будет рейс кондишн между begin; и save_current_object_value(id) %) ), но имхо это не что иное как ручное эмулирование TRANSACTION ISOLATION LEVEL SERIALIZABLE =) -- „Истина — это вовсе не то, что можно убедительно доказать, это то, что делает всё проще и понятнее“ — Антуан де Сент-Экзюпери ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 18:47 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Задача решается, если в записи object_history сохранять время окончания транзакции создавшей эту запись. Но как это сделать? Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 18:50 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
в таблицах есть скрытые служебные поля - xmin, xmax - вот xmin - это номер транзакции (он всегда только возрастает, по идеи :) ). получается нужно выбирать только те записи, у которых xmin <= txid_current() пример доступа к служебным полям xmin, xmax таблицы: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. -- „Истина — это вовсе не то, что можно убедительно доказать, это то, что делает всё проще и понятнее“ — Антуан де Сент-Экзюпери ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 19:09 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
если "вражеская" транзакция началась раньше, то xmin будет меньше txid_current() (см. последний случай), этого условия недостаточно :( Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 19:23 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
да, затупил, этож тоже самое что ttime %) ps: с пятницей :) -- „Истина — это вовсе не то, что можно убедительно доказать, это то, что делает всё проще и понятнее“ — Антуан де Сент-Экзюпери ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.04.2008, 19:36 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Ёшда, затупил, этож тоже самое что ttime %) ps: с пятницей :) С субботой однако мозг почти съеден, а проблема осталась :( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.04.2008, 03:15 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Если проблема не решается внутри системы, то на проблему надо посмотреть снаружи... :) Собственно: "А нафига?" Глядя на код у меня например возникает вопрос: "При такой структуре построения кода, зачем вообще второй вызов get_? Запиши в переменную..." Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.04.2008, 08:35 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
get_... может вызываться внутри другой хп. Код: plaintext 1. 2. 3. 4. 5. Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.04.2008, 12:11 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan Blackget_... может вызываться внутри другой хп.А чем это мешает записать в переменную? custom_variable_classes ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.04.2008, 14:44 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Vladimir Sitnikov Dan Blackget_... может вызываться внутри другой хп.А чем это мешает записать в переменную? custom_variable_classes объектов может быть 1 000 000 000... + даже если в переменную можно записать массив, доступ к его элементам будет осуществляться без индексов, что существенно замедлит работу хп + к тому же использование custom_variable_classes противоречит моей религии ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.04.2008, 16:05 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan Black Vladimir Sitnikov Dan Blackget_... может вызываться внутри другой хп.А чем это мешает записать в переменную? custom_variable_classes объектов может быть 1 000 000 000...И все они нужны одновременно? Ню ню. Сколько времени вы этот миллиард обрабатывать будете? Dan Black+ к тому же использование custom_variable_classes противоречит моей религии Ах да, религия, когда всё должно соотвествовать стандартам ansi sql-81, где нельзя менять уровни изоляции и т.п. Добавьте поддержку "select * from table as of timestamp(...)" -- глядишь не только вам пригодится. Если религия позволяет триггеры, то timetravel вам в руки ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 08:39 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Vladimir SitnikovИ все они нужны одновременно? Ню ню. Сколько времени вы этот миллиард обрабатывать будете?Ладно, нужно будет только 1000 объектов. Это что-то изменит? ;))) Vladimir SitnikovАх да, религия, когда всё должно соотвествовать стандартам ansi sql-81, где нельзя менять уровни изоляции и т.п.Религия позволяет менять уровень изоляции транзакций, но в данном случае есть строгое требование, которое нельзя обойти. Vladimir SitnikovЕсли религия позволяет триггеры, то timetravel вам в рукиПри уровне изоляции Read Commited там возникает такая же проблема, что я описал в конце своего первого топика. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 10:38 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan Black Код: plaintext 1. 2. 3. 4. 5. Проблема в том, значение объекта 100, полученное в строке "1", может отличаться от значения полученного в строке "2", так как параллельно работают другие транзакции, которые могут изменить значение объекта 100. Доп. условие задачи: Если внутри нашей транзакции у объекта изменилось значение, то при следующем вызове get_object_value должно возвратиться новое измененное значение. Изменения значения объекта в параллельных транзакциях не должны влиять на возврат функции get_object_value. наверное должен помочь SELECT ... FOR { UPDATE | SHARE } ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 11:30 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatнаверное должен помочь SELECT ... FOR { UPDATE | SHARE }Чтение не должно блокировать другие транзакции, изменение значения объекта в параллельных транзакциях не должно блокировать чтение в текущей транзакции ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 11:38 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
в самом начале транзакции узнать минимальный из xid-ов работающих сейчас транзакций, запомнить в переменную. в get_object_value делать where xmin<$OTHER_RUNNING_MIN_XID or xmin=txid_current(). при этом не будут учитываться изменения не только других работавших на момент старта транзакций, но и транзакций, ктоторые уже закончились, но начались позже какой-то из работавших на момент старта. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 12:23 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan Black Ниже описывается прототип схемы хранения истории изменения объекта и проблема, которая скоро съест мой мозг Хочется услышать мнения умных людей по поводу структуры хранения данных (таблиц и полей), и запросов к этим структурам. А так же варианты реализации задачи :) ... Доп. условие задачи: Если внутри нашей транзакции у объекта изменилось значение, то при следующем вызове get_object_value должно???? возвратиться новое измененное значение. Изменения значения объекта в параллельных транзакциях не должны влиять на возврат функции get_object_value. Пример. Код: plaintext 1. 2. 3. 4. внутри функции get_object_value делается простой запрос (к примеру) Код: plaintext внутри функции set_object_value так же делается запрос (к примеру) Код: plaintext Этих двух запросов хватает почти для всех случаев. Вот один из случаев, для которых запросы не срабатывают Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. Код: plaintext 1. ну допустим, что нужно нечто, таки похожее на историю изменения, но ведущее согласно доп условию. Тогда, в истории, если верить предыдущим комментаторам, всегда можно найти данные, записанные _этой_ транзакцией (или их отсутствие). (как получить текущую транзакцию xmin - вопрос наверное не ко мне, (хотя я могу придумать). Т.е. в get_ вы сначала лезете в историю по номеру текущей транзакции, и только при их отсутствии - ищете другие. Где-то так. Нет? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 12:30 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
LeXa NalBatв самом начале транзакции узнать минимальный из xid-ов работающих сейчас транзакций, запомнить в переменную. в get_object_value делать where xmin<$OTHER_RUNNING_MIN_XID or xmin=txid_current(). при этом не будут учитываться изменения не только других работавших на момент старта транзакций, но и транзакций, ктоторые уже закончились, но начались позже какой-то из работавших на момент старта.Переход на 8.3 планируется только через полгода, поэтому использовать txid_current() и прочих подобных функций нет возможности. + хочется решить задачу структурно (с помощью особой организации данных) (вырожденным случаем является использование sql-81 (с) Vladimir Sitnikov ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 12:34 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
4321если действительно нужна исторя изменения величины, то "дополнительное условие задачи" этому просто противоречит. ну допустим, что нужно нечто, таки похожее на историю изменения, но ведущее согласно доп условию. Тогда, в истории, если верить предыдущим комментаторам, всегда можно найти данные, записанные _этой_ транзакцией (или их отсутствие). (как получить текущую транзакцию xmin - вопрос наверное не ко мне, (хотя я могу придумать). Т.е. в get_ вы сначала лезете в историю по номеру текущей транзакции, и только при их отсутствии - ищете другие. Где-то так. Нет?Где-то так. Ищу данные записанные в этой транзакции, если не нахожу, то смотрю данные записанные транзакциями завершившимися до начала текущей транзакции. Всё это решается установкой уровня транзакции Serializable, но такой возможности нет в силу других требований. Поэтому и ломаю голову, можно ли с использованием Read Committed, решить вопрос видимости данных (через запросы и структуры данных) аналогично действию уровня Serializable. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 12:43 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Dan BlackГде-то так. Ищу данные записанные в этой транзакции, если не нахожу, то смотрю данные записанные транзакциями завершившимися до начала текущей транзакции. Всё это решается установкой уровня транзакции Serializable, но такой возможности нет в силу других требований. Поэтому и ломаю голову, можно ли с использованием Read Committed, решить вопрос видимости данных (через запросы и структуры данных) аналогично действию уровня Serializable.вы наверное меня не поняли. Я рассказал, как получить искомое при Read Committed. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 13:04 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
4321вы наверное меня не поняли. Я рассказал, как получить искомое при Read Committed.Не понял :) объясните подробнее, пожалуйста ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 13:26 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
4321... при их отсутствии - ищете другие ...вот в этот момент, если как в примере транзакция один завершилась в середине транзакции два - в выборку в транзакции два попадёт изменённое в транзакции один значение (так как номер транзакции один (её дата начала) меньше номера транзакции два) - невыходит :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 13:50 |
|
||
|
Как организовать хранение и извление исторических данных?
|
|||
|---|---|---|---|
|
#18+
Ах да, я кажется понял . Вы о повторном чтении после только чтения , а не записи. Признаю невнимательность. Ну так сделайте ф-ю get пишущей . (можно даже не туда). (Вам же надо зафиксировать сам факт чтения). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.04.2008, 15:05 |
|
||
|
|

start [/forum/topic.php?fid=53&msg=35268156&tid=2004410]: |
0ms |
get settings: |
10ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
43ms |
get topic data: |
12ms |
get forum data: |
2ms |
get page messages: |
66ms |
get tp. blocked users: |
1ms |
| others: | 225ms |
| total: | 381ms |

| 0 / 0 |
