Кто-нибудь знает подход для проверки соответствия версий родительских записей дочерним? Т.е. есть две таблицы Parent и Child. Для того чтобы отобразить их содержимое в приложении, мне нужно два запроса, select * from Parent и select * from Child. Как убедиться, что в Child что-то изменилось пока я читал Parent или наоборот.
Спасибо!
Re: Соответствие версий родительских и дочерних записей
Федя пишет: > Кто-нибудь знает подход для проверки соответствия версий родительских > записей дочерним? Т.е. есть две таблицы Parent и Child. Для того чтобы > отобразить их содержимое в приложении, мне нужно два запроса, select * > from Parent и select * from Child. Как убедиться, что в Child что-то > изменилось пока я читал Parent или наоборот.
Выполнить два запроса в одной транзакции.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Соответствие версий родительских и дочерних записей
Здравствуйте, MasterZiv, Вы писали:
MZ>Федя пишет: >> Кто-нибудь знает подход для проверки соответствия версий родительских >> записей дочерним? Т.е. есть две таблицы Parent и Child. Для того чтобы >> отобразить их содержимое в приложении, мне нужно два запроса, select * >> from Parent и select * from Child. Как убедиться, что в Child что-то >> изменилось пока я читал Parent или наоборот.
MZ>Выполнить два запроса в одной транзакции.
Не понял, а как транзакции влияют на select?
Re[2]: Соответствие версий родительских и дочерних записей
Здравствуйте, MasterZiv, Вы писали:
MZ>Федя пишет: >> Кто-нибудь знает подход для проверки соответствия версий родительских >> записей дочерним? Т.е. есть две таблицы Parent и Child. Для того чтобы >> отобразить их содержимое в приложении, мне нужно два запроса, select * >> from Parent и select * from Child. Как убедиться, что в Child что-то >> изменилось пока я читал Parent или наоборот.
MZ>Выполнить два запроса в одной транзакции.
Можно, пожалуйста, поподробнее?
Re[3]: Соответствие версий родительских и дочерних записей
Здравствуйте, Федя, Вы писали:
Ф>Здравствуйте, MasterZiv, Вы писали:
MZ>>Выполнить два запроса в одной транзакции.
Ф>Можно, пожалуйста, поподробнее?
Черновое чтение.
В пределах транзакции какие-либо изменения данных в других транзакциях не отображаются.
Таким образом, Вы всегда будете иметь данные одной версии, но, возможно, устаревшие.
Другой способ:
ставить на каждую запись время последнего изменения/добавления тригером.
И потом сравнивать дату запроса с родителю (ДЗ) и максимальную дату изменения детей (ДИЗ). При ДИЗ >= ДЗ реагировать в зависимости от логики приложения.
Re: Соответствие версий родительских и дочерних записей
Здравствуйте, Федя, Вы писали:
Ф>Спасибо!
Не за что. Начни с того, с какой СУБД (и версией) работаешь и какую задачу хочешь решить.
Ф> нужно два запроса, select * from Parent и select * from Child. Как убедиться, что в Child что-то изменилось пока я читал Parent.
Никак, если ты не читал Child ранее и тебе не с чем сравнить.
Если же ты хочешь получить то же, что читал ранее, то нужно установить для транзакции уровень изолированности не ниже REPEATABLE READ, и можно не сравнивать. Если СУБД это поддерживает.
Re[4]: Соответствие версий родительских и дочерних записей
Здравствуйте, Kvazimodo75, Вы писали:
K>Здравствуйте, Федя, Вы писали:
Ф>>Здравствуйте, MasterZiv, Вы писали:
MZ>>>Выполнить два запроса в одной транзакции.
Ф>>Можно, пожалуйста, поподробнее?
K>Черновое чтение.
K>В пределах транзакции какие-либо изменения данных в других транзакциях не отображаются.
K>Таким образом, Вы всегда будете иметь данные одной версии, но, возможно, устаревшие.
Извините, я все равно не понял. Сначала я читаю из Parent, потом (параллельно) изменяю Child, потом читаю Child и версия Child не соответствует версии Parent. Каким образом вы советуете использовать транзакции?
K>Другой способ: K>ставить на каждую запись время последнего изменения/добавления тригером.
K>И потом сравнивать дату запроса с родителю (ДЗ) и максимальную дату изменения детей (ДИЗ). При ДИЗ >= ДЗ реагировать в зависимости от логики приложения.
Если записывать дату в дочернюю таблицу, то непонятно откуда брать дату при удалении строки. А если в родительскую, то все равно не получается:
1) Я читаю Parent, смотрю ДИЗ < ДЗ
2) Кто-то поменял Child
3) Я читаю Child (версии не совпадают)
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[2]: Соответствие версий родительских и дочерних записей
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Федя, Вы писали:
Ф>>Спасибо! W>Не за что. Начни с того, с какой СУБД (и версией) работаешь и какую задачу хочешь решить.
Сервер MSSQL 2000
Ф>> нужно два запроса, select * from Parent и select * from Child. Как убедиться, что в Child что-то изменилось пока я читал Parent. W>Никак, если ты не читал Child ранее и тебе не с чем сравнить.
W>Если же ты хочешь получить то же, что читал ранее, то нужно установить для транзакции уровень изолированности не ниже REPEATABLE READ, и можно не сравнивать. Если СУБД это поддерживает.
Спасибо, с транзакциями я разобрался — все работает. Но есть ли другой способ? Не хотелось бы блокировать таблицы на время чтения всех дочерних записей. Нужна какая-то "оптимистичная" проверка. Чтобы можно было читать все таблицы по очереди, в предположении, что ничего не поменялось. А потом на стороне клиента сравнивать версии строк и заново читать изменившиеся строки (их скорее всего будет немного).
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[4]: Соответствие версий родительских и дочерних записей
Здравствуйте, Kvazimodo75, Вы писали:
K>Здравствуйте, Федя, Вы писали:
Ф>>Здравствуйте, MasterZiv, Вы писали:
MZ>>>Выполнить два запроса в одной транзакции.
Ф>>Можно, пожалуйста, поподробнее?
K>Черновое чтение.
K>В пределах транзакции какие-либо изменения данных в других транзакциях не отображаются.
K>Таким образом, Вы всегда будете иметь данные одной версии, но, возможно, устаревшие.
Вариант с транзакциями я понял, спасибо.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[3]: Соответствие версий родительских и дочерних записей
Здравствуйте, Федя, Вы писали:
Ф>Чтобы можно было читать все таблицы по очереди, в предположении, что ничего не поменялось. А потом на стороне клиента сравнивать версии строк и заново читать изменившиеся строки (их скорее всего будет немного).
Еще раз: какую задачу хочешь решить? Опиши сценарий полностью.
Re[4]: Соответствие версий родительских и дочерних записей
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Федя, Вы писали:
Ф>>Чтобы можно было читать все таблицы по очереди, в предположении, что ничего не поменялось. А потом на стороне клиента сравнивать версии строк и заново читать изменившиеся строки (их скорее всего будет немного).
W>Еще раз: какую задачу хочешь решить? Опиши сценарий полностью.
Ок, я попробую.
Есть приложение (.Net, WinForms, SQLServer), которое позволяет работать с определенным набором документов, с обычными функциями: добавление, редактирование, удаление. У каждого документа может быть одна или несколько табличных частей. Например я захожу на форму которая отображает список документов за определенный период времени. Соответственно при загрузке этой формы из базы запрашивается как главная таблица со списком документов так и куча дочерних таблиц. Так вот если в момент загрузки формы с другого рабочего места кто-то что-то меняет, то иногда получается так, что версии дочерних записей могут не сответствовать версиям родительских записей. Напрмер кто-то удалил строку из дочерней таблицы уже после того как загрузилась родительская таблица. Хотелось бы научиться определять такие коллизии и заново загружать обновившиеся документы (возможна другая реакция, не важно). Вариант с транзакциями не катит, т.к. во первых используется стандартный DataAdapter, а во вторых я думаю такой подход существенно снизит производительность приложения из-за блокировок.
Re[5]: Соответствие версий родительских и дочерних записей
Все равно мало понятно, что чему не соответствует. Ладно, по пунктам.
Ф>я захожу на форму которая отображает список документов за определенный период времени.
Так, отлично. Отображает в виде списка, надо понимать.
Ф>при загрузке этой формы из базы запрашивается как главная таблица со списком документов так и куча дочерних таблиц.
А зачем запрашиваются дочерние таблицы, ведь форма отображает только данные из главной? (или нет?)
Ф>если в момент загрузки формы с другого рабочего места кто-то что-то меняет
Ну меняет, и что в этом страшного? На то и многопользовательская система, чтобы постоянно что-то менялось.
Ф>получается так, что версии дочерних записей могут не сответствовать версиям родительских записей. Напрмер кто-то удалил строку из дочерней таблицы уже после того как загрузилась родительская таблица.
Подробнее, в чем несоответствие. Ну и что что удалил.
То, что документы меняются, пока пользователь разглядывает форму, не смущает?
Re[6]: Соответствие версий родительских и дочерних записей
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Федя, Вы писали:
W>Все равно мало понятно, что чему не соответствует. Ладно, по пунктам.
Ф>>я захожу на форму которая отображает список документов за определенный период времени. W>Так, отлично. Отображает в виде списка, надо понимать.
ну да
Ф>>при загрузке этой формы из базы запрашивается как главная таблица со списком документов так и куча дочерних таблиц. W>А зачем запрашиваются дочерние таблицы, ведь форма отображает только данные из главной? (или нет?)
нет, загружается все сразу и главная и все дочерние записи
Ф>>если в момент загрузки формы с другого рабочего места кто-то что-то меняет W>Ну меняет, и что в этом страшного? На то и многопользовательская система, чтобы постоянно что-то менялось.
да в принципе ничего страшного
Ф>>получается так, что версии дочерних записей могут не сответствовать версиям родительских записей. Напрмер кто-то удалил строку из дочерней таблицы уже после того как загрузилась родительская таблица. W>Подробнее, в чем несоответствие. Ну и что что удалил.
если удален весь документ, между чтением родительких и дочерних записей, то в приложении можно увидеть документ но с пустыми табличными частями
W>То, что документы меняются, пока пользователь разглядывает форму, не смущает?
Если ты намекаешь про то что два пользователя могут одновременно менять один документ, то нет, т.к. есть соответствующая проверка. Читается timestamp строки документа и при сохранении изменений проверяется не изменился ли он в базе. Также есть триггеры которые меняют timestamp в родительской строке при изменении дочерних записей.
Re[7]: Соответствие версий родительских и дочерних записей
Здравствуйте, Федя, Вы писали:
Ф>нет, загружается все сразу и главная и все дочерние записи
А это действительно необходимо? Если читать дочерние таблицы только по мере необходимости, когда пользователь выбрал документ и попросил показать табличную часть, то шансов выдать ему неактуальные данные будет гораздо меньше.
Ф>если удален весь документ, между чтением родительких и дочерних записей, то в приложении можно увидеть документ но с пустыми табличными частями
Ну вот, наконец-то проблема обозначена.
В случае с MSSQL 2000, насколько мне известно, решить ее можно только одним способом: читать все части документа в одной транзакции. (Если есть другой способ, пусть меня поправят.) Для того, чтобы не мешать при этом другим пользователям, нужно сделать эту транзакцию как можно короче. Начать с того, что читать по одному документу за раз, а не помногу. Далеее, если запись из главной таблицы была прочитана ранее, можно проверить, не удалена ли она. Например так:
select * from child where id_parent = (select id from parent where id = ?)
W>>То, что документы меняются, пока пользователь разглядывает форму, не смущает? Ф>Если ты намекаешь про то что два пользователя могут одновременно менять один документ, то нет, т.к. есть соответствующая проверка.
Я намекал на то, что документ может измениться в любой момент, а не только во время чтения.
Re[8]: Соответствие версий родительских и дочерних записей
Здравствуйте, wildwind, Вы писали:
W>Здравствуйте, Федя, Вы писали:
Ф>>нет, загружается все сразу и главная и все дочерние записи
W>А это действительно необходимо? Если читать дочерние таблицы только по мере необходимости, когда пользователь выбрал документ и попросил показать табличную часть, то шансов выдать ему неактуальные данные будет гораздо меньше.
конечно так было бы лучше, но этот вопрос за рамками обсуждемой проблемы
Ф>>если удален весь документ, между чтением родительких и дочерних записей, то в приложении можно увидеть документ но с пустыми табличными частями
W>Ну вот, наконец-то проблема обозначена.
это только один случай. есть более сложные, например когда значения в дочерних строках связаны между собой.
W>В случае с MSSQL 2000, насколько мне известно, решить ее можно только одним способом: читать все части документа в одной транзакции. (Если есть другой способ, пусть меня поправят.) Для того, чтобы не мешать при этом другим пользователям, нужно сделать эту транзакцию как можно короче. Начать с того, что читать по одному документу за раз, а не помногу. Далеее, если запись из главной таблицы была прочитана ранее, можно проверить, не удалена ли она. Например так: W>
select * from child where id_parent = (select id from parent where id = ?)
Не вариант, если я буду читать по одной строке, скорость чтения будет в десятки раз (зависит от количества документов) меньше
W>>>То, что документы меняются, пока пользователь разглядывает форму, не смущает? Ф>>Если ты намекаешь про то что два пользователя могут одновременно менять один документ, то нет, т.к. есть соответствующая проверка. W>Я намекал на то, что документ может измениться в любой момент, а не только во время чтения.
Это не так важно, главное чтобы не нарушалась целостность документа. Т.е. если документ меняется то он должен меняться весь, как единое целое.
Re[9]: Соответствие версий родительских и дочерних записей
Федя wrote:
> Ф>>если удален весь документ, между чтением родительких и дочерних > записей, то в приложении можно увидеть документ но с пустыми табличными > частями
При любых изменениях документа или его частей — обновлять ревизию документа (timestamp или проще и надёжнее "update Doc set rev=rev+1 where id=?"). Далее действовать просто:
1. Начинаем загружать документ. Читаем его ревизию, запоминаем.
2. Грузим части документа.
3. Проверяем, что ревизия документа равна запомненной.
3.1 Если такая же — показываем документ.
3.2 Если различается — действовать по обстоятельствам, вероятнее всего переход на шаг 1.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Соответствие версий родительских и дочерних записей
wildwind wrote:
> select * from child where id_parent = (select id from parent where id = ?)
А какое это имеет смысл? Это абсолютно эквивалентно
select * from child where id_parent = ?
(при наличии fk, что обязательно должно быть)
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[10]: Соответствие версий родительских и дочерних записей
Здравствуйте, ., Вы писали:
.>Федя wrote:
>> Ф>>если удален весь документ, между чтением родительких и дочерних >> записей, то в приложении можно увидеть документ но с пустыми табличными >> частями .>При любых изменениях документа или его частей — обновлять ревизию документа (timestamp или проще и надёжнее "update Doc set rev=rev+1 where id=?"). Далее действовать просто: .>1. Начинаем загружать документ. Читаем его ревизию, запоминаем. .>2. Грузим части документа. .>3. Проверяем, что ревизия документа равна запомненной. .>3.1 Если такая же — показываем документ. .>3.2 Если различается — действовать по обстоятельствам, вероятнее всего переход на шаг 1.
Т.е. загружаем документы, запоминаем версии, потом загружаем части, а потом опять загружаем документ и проверяем изменилась ли версия? Да, это нормальный вариант. Единственное я хотел бы избежать двойной загрузки базовой таблицы, т.к. это немного дольше.
Можно объединять дочерние записи с базовой таблицей, чтобы читать версии документа сразу с загрузкой дочерних строчек. Только если дочерних строчек у документа нет, то нет и версии Не могу пока ничего придумать.
Re[4]: Соответствие версий родительских и дочерних записей
Здравствуйте, Kvazimodo75, Вы писали:
K>Здравствуйте, Федя, Вы писали:
K>Другой способ: K>ставить на каждую запись время последнего изменения/добавления тригером.
K>И потом сравнивать дату запроса с родителю (ДЗ) и максимальную дату изменения детей (ДИЗ). При ДИЗ >= ДЗ реагировать в зависимости от логики приложения.
Кстати, не сочтите за издевательство, думаю вы поймете. А что, если между чтениями из базы кто-то переведет часы?
Re[3]: Соответствие версий родительских и дочерних записей