Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 08:13
Оценка:
Всем привет.

Господа ГУРУ проектирования, нуждаюсь в вашем совете.

Есть база данных с где-то 20 таблицами, из которых 10 справочники. База содержит данные о подразделениях компании. Есть главная таблица "Подразделение" и все остальные связаны с ней.
Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.
Осложняет задачу наличие информации вида "список зданий подразделения", "список фотографий каждого здания". И это тоже надо редактировать.

Сейчас остановился на варианте заведения таблицы вида (ИД проекта, имя таблицы, имя поля, новое значение поля, операция (удаление, изменение, вставка)). Пытаюсь _красиво_ реализовать загрузку и сохранение данных в эту таблицу.
Вариант с дублирование таблиц и тем более заведением отдельной базы для хранения изменений отбросил из соображений неэкономности и "некрасивости".

У кого-то есть опыт реализации такой задачи? Поделитесь плиз

P.S. Использую Hibernate3.
Re: Программная реализация длинных транзакций
От: Аноним  
Дата: 12.09.06 11:29
Оценка: 6 (1)
Ну а если список операций представлять в виде команд и сериализовать его в таблицу базы? Когда надо корзинку сохранить — поднимаешь список команд и одну за другой выполняешь — все падает в базу. Если что-то не может упасть в связи с тем что данные устарели — отваливается только одна команда из списка — соответственно можно уведомить пользователя и, возможно, исправить ситуацию.
Re[2]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 12:09
Оценка:
Спасибо за проявленное внимание


Ну а если список операций представлять в виде команд и сериализовать его в таблицу базы? Когда надо корзинку сохранить — поднимаешь список команд и одну за другой выполняешь — все падает в базу. Если что-то не может упасть в связи с тем что данные устарели — отваливается только одна команда из списка — соответственно можно уведомить пользователя и, возможно, исправить ситуацию.


Интересная мысль...
А как получить данные для дальнейшего редактирования? Надо вытащить данные из базы и накатить на них изменения из корзинки. Если это структурированные данные — еще куда ни шло. А если SQL комманды, то проблема.
Re: Программная реализация длинных транзакций
От: pt4h Беларусь http://dzmitryhuba.blogspot.com/
Дата: 12.09.06 12:13
Оценка: 2 (1)
Здравствуйте, Michael_Y, Вы писали:

M_Y> Всем привет.


M_Y> Господа ГУРУ проектирования, нуждаюсь в вашем совете.


M_Y> Есть база данных с где-то 20 таблицами, из которых 10 справочники. База содержит данные о подразделениях компании. Есть главная таблица "Подразделение" и все остальные связаны с ней.

M_Y> Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.
M_Y> Осложняет задачу наличие информации вида "список зданий подразделения", "список фотографий каждого здания". И это тоже надо редактировать.

M_Y> Сейчас остановился на варианте заведения таблицы вида (ИД проекта, имя таблицы, имя поля, новое значение поля, операция (удаление, изменение, вставка)). Пытаюсь _красиво_ реализовать загрузку и сохранение данных в эту таблицу.

M_Y> Вариант с дублирование таблиц и тем более заведением отдельной базы для хранения изменений отбросил из соображений неэкономности и "некрасивости".

M_Y> У кого-то есть опыт реализации такой задачи? Поделитесь плиз


Очень важный момент — возможность одновременного редактирования. То есть, два пользователя имеют или нет возможность редактировать одни и те же сущности. Если возможность есть, надо предусмотреть уровни изоляции (хинт: посмотрите Isolation Level).

Если же редактировать может только один пользователь, то опять есть два варианта решения:
  1. Делать копию записей, которые необходимо редактировать и работать с ними — в этом случае остальные пользователи будут видеть оригинальные данные (которые были до Ваших изменений) до того момента комита Ваших изменений.
  2. Есть смысл посмотреть в сторону паттерна Command с поддержкой отмены. Если Вам удастся реализвать все операции через, то впринципе реализация будет закдючаться в серилизации набора команд в какое-то хранилище + серилизации состояния редактируемых объектов на момент начала редактирования. Накатывание изменений будет заключаться в последовательном выполнении команд.

M_Y>P.S. Использую Hibernate3.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Программная реализация длинных транзакций
От: wildwind Россия  
Дата: 12.09.06 12:25
Оценка: +1
Здравствуйте, Michael_Y, Вы писали:

M_Y> Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.


А чем вызвана такая необходимость откладывать работу на неопределенный срок? При такой модели неизбежны конфликты и возможна потеря данных. Пользователь, вылезший через месяц из своей корзинки-песочницы, может просто не узнать базу. И будет еще неделю соображать, какие из сделанных им изменений еще актуальны, а какие уже нет.
Re[2]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 12:48
Оценка:
Здравствуйте, pt4h, Вы писали:

M_Y>> Всем привет.


M_Y>> Господа ГУРУ проектирования, нуждаюсь в вашем совете.


M_Y>> Есть база данных с где-то 20 таблицами, из которых 10 справочники. База содержит данные о подразделениях компании. Есть главная таблица "Подразделение" и все остальные связаны с ней.

M_Y>> Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.
M_Y>> Осложняет задачу наличие информации вида "список зданий подразделения", "список фотографий каждого здания". И это тоже надо редактировать.

M_Y>> Сейчас остановился на варианте заведения таблицы вида (ИД проекта, имя таблицы, имя поля, новое значение поля, операция (удаление, изменение, вставка)). Пытаюсь _красиво_ реализовать загрузку и сохранение данных в эту таблицу.

M_Y>> Вариант с дублирование таблиц и тем более заведением отдельной базы для хранения изменений отбросил из соображений неэкономности и "некрасивости".

M_Y>> У кого-то есть опыт реализации такой задачи? Поделитесь плиз


P>Очень важный момент — возможность одновременного редактирования. То есть, два пользователя имеют или нет возможность редактировать одни и те же сущности. Если возможность есть, надо предусмотреть уровни изоляции (хинт: посмотрите Isolation Level).

Не нужна, к счатью Редактирует только один человек.

P>Если же редактировать может только один пользователь, то опять есть два варианта решения:

P>

    P>
  1. Делать копию записей, которые необходимо редактировать и работать с ними — в этом случае остальные пользователи будут видеть оригинальные данные (которые были до Ваших изменений) до того момента комита Ваших изменений.
    P>
  2. Есть смысл посмотреть в сторону паттерна Command с поддержкой отмены. Если Вам удастся реализвать все операции через, то впринципе реализация будет закдючаться в серилизации набора команд в какое-то хранилище + серилизации состояния редактируемых объектов на момент начала редактирования. Накатывание изменений будет заключаться в последовательном выполнении команд.
    P>

Про вариант делать копию думал. Не понравился "некрасивостью".
На Command смотрю. Спасибо. Похоже, пригодится.
Насчет последовательности выполнения. Мне так кажется, нет необходимости хранить последовательность действий. Реализации Command будут сами решать что надо выполнить сначала, а что потом. У меня одна главная таблица, к которой идут связки от остальных таблиц. Поэтому достаточно будет дать команду вида MainTable.update(тфблица, имя поля, новое значение).
Re[2]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 12:52
Оценка:
Здравствуйте, wildwind, Вы писали:

M_Y>> Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.


W>А чем вызвана такая необходимость откладывать работу на неопределенный срок? При такой модели неизбежны конфликты и возможна потеря данных. Пользователь, вылезший через месяц из своей корзинки-песочницы, может просто не узнать базу. И будет еще неделю соображать, какие из сделанных им изменений еще актуальны, а какие уже нет.


Изменения должны согласоываться с разными отделами. Это дело может быть долгим.
Также планируется сделать такую схему работу единственным способом внесения изменений в базу. А отслеживать програмно, чтобы каждый объект редактировал только один пользователь не составит труда.
Re[3]: Программная реализация длинных транзакций
От: wildwind Россия  
Дата: 12.09.06 13:03
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y> Изменения должны согласоываться с разными отделами. Это дело может быть долгим.


Я понимаю, что изменения в структуре подразделений крупной компании не делаются быстро. Но почему транзакция БД должна быть "длинной", вот это непонятно. Все равно после всей волокиты имеется утвержденный бумажный документ с которого и вбиваются данные, за 5 минут.
Re: Программная реализация длинных транзакций
От: achmed Удмуртия https://www.linkedin.com/in/nail-achmedzhanov-9907188/
Дата: 12.09.06 13:09
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y> Всем привет.

M_Y> Господа ГУРУ проектирования, нуждаюсь в вашем совете.
M_Y> Есть база данных с где-то 20 таблицами, из которых 10 справочники. База содержит данные о подразделениях компании. Есть главная таблица "Подразделение" и все остальные связаны с ней.
M_Y> Задача — вносить изменения в базу "проектами". Т.е. выбираем подразделение для редактирования, правим что хотим, сохраняем изменения в какую-то "корзинку", через пару недель возвращаемся к редактированию этого подразделения. Еще через неделю одним махом применяем изменения на базе.
M_Y> Осложняет задачу наличие информации вида "список зданий подразделения", "список фотографий каждого здания". И это тоже надо редактировать.


Один из вариантов, который пришел в голову:

Добавить второй вид персистентности для обьектов — xml хранилище.

"Недоделанные" обьекты сохраняются в в формате xml (в файл, БД, куда угодно).
Когда нужно выполнить действие "одним махом применяем изменения на базе"
произвести репликацию между содержимым БД и тем что в корзине.
Re[4]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 13:15
Оценка:
Здравствуйте, wildwind, Вы писали:

M_Y>> Изменения должны согласоываться с разными отделами. Это дело может быть долгим.


W>Я понимаю, что изменения в структуре подразделений крупной компании не делаются быстро. Но почему транзакция БД должна быть "длинной", вот это непонятно. Все равно после всей волокиты имеется утвержденный бумажный документ с которого и вбиваются данные, за 5 минут.


Этот документ делается автоматом на основе внесенных изменений. А перенос данных из корзинки в базу происходит по утверждению этого документа.
Re[2]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 13:24
Оценка:
Здравствуйте, achmed, Вы писали:

A>Один из вариантов, который пришел в голову:


A>Добавить второй вид персистентности для обьектов — xml хранилище.


A>"Недоделанные" обьекты сохраняются в в формате xml (в файл, БД, куда угодно).

A>Когда нужно выполнить действие "одним махом применяем изменения на базе"
A>произвести репликацию между содержимым БД и тем что в корзине.

Приблизитель то, чем я сейчас и занимаюсь, но без XML.
Мне неясно как построить внутреннюю структуру загрузки/сохранения в смысле разделения обязанностей. Хочется сделать "правильно" и просто
Re[5]: Программная реализация длинных транзакций
От: wildwind Россия  
Дата: 12.09.06 13:28
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y> Этот документ делается автоматом на основе внесенных изменений. А перенос данных из корзинки в базу происходит по утверждению этого документа.


Так, первичные документы в электронной форме? Ну тогда извините, все гораздо, гораздо сложнее. Тут целая инфраструктура нужна. Или вы пишете заказную систему документооборота?

Мне кажется, тут нужен подход подобный VCS системам. Каждая черновая версия после очередного изменения/предложения — объект, экземпляр некой сущности, и следовтельно обладает устойчивостью (persistence).

По-любому выходит что длинные транзакции не нужны.
Re[6]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 12.09.06 13:40
Оценка:
Здравствуйте, wildwind, Вы писали:

M_Y>> Этот документ делается автоматом на основе внесенных изменений. А перенос данных из корзинки в базу происходит по утверждению этого документа.


[чик-чик]

W>Мне кажется, тут нужен подход подобный VCS системам. Каждая черновая версия после очередного изменения/предложения — объект, экземпляр некой сущности, и следовтельно обладает устойчивостью (persistence).

VCS системы хранят историю изменений, насколько я знаю. Менее продвинутые snapshot'ы. А мне нужно хранить только последнее изменение и уметь получать его. Причем с использованием Hibernate.

W>По-любому выходит что длинные транзакции не нужны.

Я просто не придумал более подходящего заголовка
Re[7]: Программная реализация длинных транзакций
От: wildwind Россия  
Дата: 12.09.06 14:25
Оценка: 1 (1)
Здравствуйте, Michael_Y, Вы писали:

M_Y> VCS системы хранят историю изменений, насколько я знаю. Менее продвинутые snapshot'ы. А мне нужно хранить только последнее изменение и уметь получать его.


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

По сути: можно завести объект "изменение" для каждого элементарного объекта ("список зданий", "список фотографий" и т.д. — у вас ведь составной объект). Физически их можно хранить в тех же таблицах что и актуальные версии, с признаком типа изменения: insert/update/delete. Определить ограничение целостности: на каждый экземпляр эл. объекта имеется не более одного изменения.

Далее определить операции:
1) "merge" для каждого эл. объекта в составе данного сложного объекта берется актуальная версия и применяются все имеющиеся изменения — в вашем случае одно.
2) "diff" — обратная к merge.

Для редактирования (промежуточного) пользователю выдается результат merge, в базу записывается результат diff.
Re[3]: Программная реализация длинных транзакций
От: dotnetcoder  
Дата: 12.09.06 22:25
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y>Здравствуйте, achmed, Вы писали:


A>>Один из вариантов, который пришел в голову:


A>>Добавить второй вид персистентности для обьектов — xml хранилище.


A>>"Недоделанные" обьекты сохраняются в в формате xml (в файл, БД, куда угодно).

A>>Когда нужно выполнить действие "одним махом применяем изменения на базе"
A>>произвести репликацию между содержимым БД и тем что в корзине.

M_Y> Приблизитель то, чем я сейчас и занимаюсь, но без XML.

M_Y> Мне неясно как построить внутреннюю структуру загрузки/сохранения в смысле разделения обязанностей. Хочется сделать "правильно" и просто


На самом деле всё просто, если берутся записи из базы для редактирования то каждую изменённую запись копировать в новый row в той же самой таблице
с пометкой dirty=1 и скажем номером версии , нулевая версия с dirty=0 принять за основную запись. если надо будет одним махом запендюрить всё на свои
места то всё можно сделать в одной транзакции используюя только последнии ревизии, после чего весь временный хлам так же легко удаляется.
автоматичискую генерацию ревизий можно организовать на триггере если dirty будет установлен в 1

P.S: RSDN@Home злобно воспротивился моим поползновениям что-либо отвечать из его встроенного редактора, обласкал гад вопросами вместо русских
пукофок, пришлось в FF отвечать. Вопчем RSDN@Home нихрена не совместим с Windows XP Prof SP2 German
Re[4]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 13.09.06 14:11
Оценка:
Здравствуйте, dotnetcoder, Вы писали:

A>>>Один из вариантов, который пришел в голову:


A>>>Добавить второй вид персистентности для обьектов — xml хранилище.


A>>>"Недоделанные" обьекты сохраняются в в формате xml (в файл, БД, куда угодно).

A>>>Когда нужно выполнить действие "одним махом применяем изменения на базе"
A>>>произвести репликацию между содержимым БД и тем что в корзине.

M_Y>> Приблизитель то, чем я сейчас и занимаюсь, но без XML.

M_Y>> Мне неясно как построить внутреннюю структуру загрузки/сохранения в смысле разделения обязанностей. Хочется сделать "правильно" и просто

D>На самом деле всё просто, если берутся записи из базы для редактирования то каждую изменённую запись копировать в новый row в той же самой таблице

D>с пометкой dirty=1 и скажем номером версии , нулевая версия с dirty=0 принять за основную запись. если надо будет одним махом запендюрить всё на свои
D>места то всё можно сделать в одной транзакции используюя только последнии ревизии, после чего весь временный хлам так же легко удаляется.
D>автоматичискую генерацию ревизий можно организовать на триггере если dirty будет установлен в 1
Не хотелось бы править структуру таблиц. Думаю, получится сделать логику только на Application Server.

D>P.S: RSDN@Home злобно воспротивился моим поползновениям что-либо отвечать из его встроенного редактора, обласкал гад вопросами вместо русских

D>пукофок, пришлось в FF отвечать. Вопчем RSDN@Home нихрена не совместим с Windows XP Prof SP2 German
Re[8]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 13.09.06 14:14
Оценка:
Здравствуйте, wildwind, Вы писали:

M_Y>> VCS системы хранят историю изменений, насколько я знаю. Менее продвинутые snapshot'ы. А мне нужно хранить только последнее изменение и уметь получать его.


W>По сути: можно завести объект "изменение" для каждого элементарного объекта ("список зданий", "список фотографий" и т.д. — у вас ведь составной объект). Физически их можно хранить в тех же таблицах что и актуальные версии, с признаком типа изменения: insert/update/delete. Определить ограничение целостности: на каждый экземпляр эл. объекта имеется не более одного изменения.

Я сделал общий объект изменений и делаю набор классов, которые будут применять изменения.

W>Далее определить операции:

W>1) "merge" для каждого эл. объекта в составе данного сложного объекта берется актуальная версия и применяются все имеющиеся изменения — в вашем случае одно.
W>2) "diff" — обратная к merge.
О, те названия функций, что я искал Спасибо.

W>Для редактирования (промежуточного) пользователю выдается результат merge, в базу записывается результат diff.

Результат diff будет сложновато получить. Я использую Hibernate.
Re[9]: Программная реализация длинных транзакций
От: wildwind Россия  
Дата: 13.09.06 15:56
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y> Результат diff будет сложновато получить. Я использую Hibernate.

Почему? И причем тут Hibernate, это ведь делается в программе.
Re[5]: Программная реализация длинных транзакций
От: dotnetcoder  
Дата: 13.09.06 17:44
Оценка:
Здравствуйте, Michael_Y, Вы писали:

M_Y> Не хотелось бы править структуру таблиц. Думаю, получится сделать логику только на Application Server.


На самом-то деле надо всего одну дополнительню колонку на таблицу, dirty флаг можно забыть и взять за основу что
версия 0 всегда оригинальная, но как говориться кому шашечки а кому ехать.
Re[10]: Программная реализация длинных транзакций
От: Michael_Y Украина  
Дата: 14.09.06 05:27
Оценка:
Здравствуйте, wildwind, Вы писали:

M_Y>> Результат diff будет сложновато получить. Я использую Hibernate.

W>Почему? И причем тут Hibernate, это ведь делается в программе.
Hibernate при том, что я использую. Поэтому когда я вытягиваю данные из базы в классы, замапленные через Hibernate, а потом делаю на них merge, надо следить, чтобы мои изменения не применились на базе.
Другая проблема — как получить diff, т.к. diff будет разницей между содержимым базы и переданными значениями из JSP. Но я пока что не сильно думал на эту тему.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.