kika: (Default)
[personal profile] kika
Вроде бы простая задача а у Грубера не описана - я хочу для каждой строки в базе данных сохранять версии. Решение в лоб - вместо UPDATE - INSERT с обновленным таймстампом. Но тогда любая выборка превращается в адъ. Наверняка это популярная проблема а я просто лох, но все что я ни придумаю получается криво.

Date: 2010-09-20 05:08 pm (UTC)
From: [identity profile] itman.livejournal.com
Любая выбора не превращается в ад. Просто при обновлении нужно писать условие, что хочешь обновить запись, у которой timestamp совпадает со считанным timestamp. И тады, если кто-то другой поменял эту запись, получаешь not found.

Борландовский Interbase, если я правильно помню, работает по такому принципу.

Date: 2010-09-20 05:21 pm (UTC)
From: [identity profile] aseleznyov.livejournal.com
Завести таблицу хххAudit и писать в нее перед UPDATE предыдущую версию таблицы xxx. Выборки - по основной таблице будут "как обычно". Вставка - тоже. А если индексы и ВК не делать на xxxAudit, то и UPDATE будет не сильно медленнее.

Date: 2010-09-20 05:26 pm (UTC)
From: [identity profile] vvs2002.livejournal.com
Это с чего это вдруг получаешь not found? Старая-то запись никуда не денется.

Я, конечно, не dba, но чтобы немного приуменьшить адъ, можно добавить флаг active row (indexed). Соответственно вместо update у нас будет update предыдущей active record to inactive и insert с новым TS/active.

Date: 2010-09-20 05:28 pm (UTC)
From: [identity profile] itman.livejournal.com
UPDATE SET ..., timestamp = now() WHERE timestamp = old_now

Когда второй клиент попытается проделать такой же фокус, он получит сапогом в лоб :-)

Date: 2010-09-20 05:29 pm (UTC)
From: [identity profile] vvs2002.livejournal.com
Во! Только писать наверное не всю таблицу, а только updated row.

Date: 2010-09-20 05:31 pm (UTC)
From: [identity profile] vvs2002.livejournal.com
Читаем условия.
ВМЕСТО
update t set timestamp ...., пишем
insert into t ('blah', 'blah', now())

Date: 2010-09-20 05:47 pm (UTC)
From: [identity profile] squadette.livejournal.com
CQRS тебе в помощь, вот я бля буду.

Date: 2010-09-20 05:51 pm (UTC)
From: [identity profile] aseleznyov.livejournal.com
Ну да, строку, конечно. "Это я с тупым углом перепутал".

Date: 2010-09-20 05:58 pm (UTC)
From: [identity profile] itman.livejournal.com
Ok, да не посмотрел. Тогда, любая выборка, конечно же, превращается в неприятное занятие. Если только не соорудить триггер, который будет обновлять флажок newest

Date: 2010-09-20 06:49 pm (UTC)
From: [identity profile] dimas.livejournal.com
мы делали вторую таблицу истории, и фигачили туда триггерами создание, изменение, удаление, в т.ч. какой узер сделалал ...

Date: 2010-09-20 07:40 pm (UTC)
From: [identity profile] 109.livejournal.com
это стук в подвале. всё зависит от того, как реализована identity в твоей таблице (и вообще какие констрейнты), а также от того, что ты с историей хочешь делать (e.g. какие queries ты хочешь на ней ранить и какие из них ты хочешь ранить эффективно). с другой стороны, упоминание о том, что в твоей таблице есть какое-то поле типа timestamp никак не помогает конкретизировать решение - так же как не поможет и упоминание о том, что там есть, скажем, int.

Date: 2010-09-20 09:12 pm (UTC)
From: [identity profile] senya.livejournal.com
Insert вместо update называется "bitemporal database". Как писать - понятно, читать, как было справедливо подмечено, несколько сложнее.
Дешевый вариант был подсказан - триггер на запись, который пишет копию обновляемой сторки в таблицу с точно таким же набором полей + поле для даты транзакции.
Выбор определяется задачей.

Date: 2010-09-20 11:07 pm (UTC)
From: [identity profile] kika.livejournal.com
Идея с триггером и флажком проста, и в голову мне не приходила, спасибо.

Date: 2010-09-20 11:11 pm (UTC)
From: [identity profile] kika.livejournal.com
Индексы придется делать, иначе любая выборка по версиям превратится в адъ. Но вообще перспективно, да.

Date: 2010-09-20 11:12 pm (UTC)
From: [identity profile] kika.livejournal.com
Типа CouchDB, да? Я думал в эту сторону, тем более что сервер-сайд понятно на чем, но как-то боязно пока. С другой стороны, зубов бояться...

Date: 2010-09-20 11:13 pm (UTC)
From: [identity profile] kika.livejournal.com
А что именно фигачили, просто предыдущую копию строки как выше предложили, или как-то покомпактнее?

Date: 2010-09-20 11:14 pm (UTC)
From: [identity profile] kika.livejournal.com
Первое место среди бессмысленных ответов! Почему-то все остальные поняли.
вот как безблагодатно влияет Мелкософт

Date: 2010-09-20 11:16 pm (UTC)
From: [identity profile] kika.livejournal.com
спасибо за термин, википедия просветляет.

Date: 2010-09-20 11:41 pm (UTC)
From: [identity profile] dimas.livejournal.com
предыдущую копию, таймстам, юзер, тип операции.

у нас смысла как-то не было делать компактнее - все-таки такое делалось на не самых часто меняемых таблицах.

Date: 2010-09-21 12:54 am (UTC)
From: [identity profile] 109.livejournal.com
тьфу, во невежество-то где. ну давай, добавляй флажок newest, посмотри, что с твоими unique constraints произойдёт. а также с производительностью запросов, которые использовали факт уникальности. с отдельной таблицей будут примерно те же проблемы, только в профиль. ты, похоже, даже не смог осознать того, что я говорю, уж не говоря о том, чтобы act on it. продолжай надувать щёки.

Date: 2010-09-21 01:25 am (UTC)
From: [identity profile] itman.livejournal.com
Правда она не бесплатная. В смысле производительности.
Edited Date: 2010-09-21 01:25 am (UTC)

Date: 2010-09-21 04:21 am (UTC)
From: [identity profile] dobryj-fei.livejournal.com
лучше версионировать цифрами инкрементальными а не таймстемпом - оказалось, что Java может на windows например генерить два идентичных TS в рамках 13 миллисекунд, ну и просто алгоритмически некоторые деятели писали дважды.

Ну и если очень заботит производительность на вставке и выборке и хочется приключений - можно иметь теневую таблицу в которую daemon будет в off-peak time выносить версионные записи. При этом быть готовым, что есть шанс что редкие версионные записи есть в основной таблице.

Date: 2010-09-21 05:18 am (UTC)
From: [identity profile] msh.livejournal.com
Так на виндовз стандартный тик - 64 Hz, это надо HPET включать чтобы больше разрешение было (multimedia timers, кажется, у них это называется)

Date: 2010-09-21 10:40 am (UTC)
From: [identity profile] kika.livejournal.com
Ну это-то как раз вполне ожидаемо.

Date: 2010-09-21 10:42 am (UTC)
From: [identity profile] kika.livejournal.com
Щеки пока надул ты, пользы никакой, а понтов много. Куда уж мне осознать как "ранить queries" и чем это отличается от "running кверис". А это единственная хотя бы забавная информация из высокоценного коммента с прямой доставкой из Редмонда.

Date: 2010-09-21 10:45 am (UTC)
From: [identity profile] kika.livejournal.com
Да это понятно всё, это ж примитивный пример, иллюстрирующий вопрос, а не объясняющий архитектуру того что я хочу построить. Про то что часики на компутере бегают заметно медленнее чем сам компутер щелкает я какбе в курсе. Любовно отполированная лбом ручка _этих_ грабель уже успела потускнеть.

Date: 2010-09-21 11:04 pm (UTC)
From: [identity profile] pzz.livejournal.com
У SQLite в примерах на сайте было где-то, как сделать базу с undo. Они сохраняли лог операций с помощью триггера, ну и откатывались с помощью него. Думаю, допилить этот пример (если тебе удастся его найти; ссылку я, естественно, не приведу) до нужной тебе базы с версионированием будет не сложно

Profile

kika: (Default)
kika

January 2017

S M T W T F S
1234567
89 1011121314
151617181920 21
22232425262728
293031    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 22nd, 2026 12:56 pm
Powered by Dreamwidth Studios