|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
И снова здравствуйте. Имеется три таблицы: Код: plaintext 1. 2. 3. 4.
В один прекрасный момент требуется обновить поле value в таблицах MEMBERS и RECORDS для некоторого id_grp. При этом они должны быть обновлены все разом, в одной транзакции. Само обновление выглядит так: считывается текущее значение, обрабатывается, на его место записывается новое, кроме того эти поля в этих таблицах зависимы друг от друга. В силу непреодолимых технических причин процесс обновления может занимать до нескольких [десятков] минут и по его завершению не обновлённые записи становятся невалидными. Соответственно, если в этот момент какой-то пользователь изменит запись или добавит новую в таблицу RECORDS с этим же id_grp (читать можно), то процесс придётся начинать сначала. Вопрос: как правильно реализовать такое обновление? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:09 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpВопрос: как правильно реализовать такое обновление? Как вариант, можно сначала обновить "без обновления" (UPDATE RECORDS SET id_grp=id_grp WHERE...). И если это удалось - то отлуп получат уже другие транзакции, пытающиеся изменить эти записи. А эта при реальном обновлении по этой причине уже не отпадет. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:14 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp, select for update испробован? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:14 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpВопрос: как правильно реализовать такое обновление? Транзакция уровня consistency. Возможно, даже с table preserve или явной блокировкой таблицы от записи. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:16 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
pastoralekcvp, select for update испробован? Нет ещё, я вот и интересуюсь в каком направлении копать. Спасибо. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:26 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Dimitry SibiryakovТранзакция уровня consistency Да это понятно. Это не убережет еще не измененные записи от изменения в других транзакциях. pastorselect for update испробован? Да, это вроде как раз для этого и придумано. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:27 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockalekcvpВопрос: как правильно реализовать такое обновление? И если это удалось - то отлуп получат уже другие транзакции, пытающиеся изменить эти записи. Это не помешает добавлению новых записей, как я понимаю? ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:27 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
23.04.2018 17:14, pastor пишет: > select for update испробован? глупость Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:27 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpЭто не помешает добавлению новых записей, как я понимаю? Нет, конечно не помешают. Но если должно помешать - то ни update, ни select for update не помогут. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:28 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockalekcvpЭто не помешает добавлению новых записей, как я понимаю? Нет, конечно не помешают. Но если должно помешать - то ни update, ни select for update не помогут. Ну в данный момент у меня тупо блокируются все три таблицы на изменение, но мне почему-то кажется что это неверный подход... ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:29 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
23.04.2018 17:29, alekcvp пишет: > мне почему-то кажется что это неверный подход... не парься. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:31 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Отозвать грант на запись у простых смертных? Навесить триггеры и проверять комбинацию спец юзера и некоего флага в некой табличке? Было бы желание. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:32 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
А запрос вида: update table set id = id where ... вызывает реально какие-нибудь изменения в базе или нет? Ещё есть идея поставить в records триггер на добавление записей типа: select id from groups where id = new.id_grp with lock; и тогда добавление будет обламываться, если запись в groups уже заблокирована кем-то. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:33 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpНу в данный момент у меня тупо блокируются все три таблицы на изменение, но мне почему-то кажется что это неверный подход... И как же тогда возможно alekcvpесли в этот момент какой-то пользователь изменит запись или добавит новую в таблицу RECORDS ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:34 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpА запрос вида: update table set id = id where ... вызывает реально какие-нибудь изменения в базе или нет?смотря что подразумевается под "..." ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:34 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
23.04.2018 17:33, alekcvp пишет: > Ещё есть идея способов достичь нирваны через анус превеликое множество. но нужно ли тебе это, при нормальной ориентации? Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:34 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpА запрос вида: update table set id = id where ... вызывает реально какие-нибудь изменения в базе или нет? Да. Добавляется версия записи. Как и при вызове SELECT FOR UPDATE WITH LOCK. ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:36 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Мимопроходящий23.04.2018 17:33, alekcvp пишет: > Ещё есть идея способов достичь нирваны через анус превеликое множество. но нужно ли тебе это, при нормальной ориентации? Ну, в идеале, мне хочется чтобы это обновление блокировало только записи связанные с обновляемой группой, позволяя нормально работать со всеми остальными... ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:36 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
23.04.2018 17:36, alekcvp пишет: > Ну, в идеале, мне хочется чтобы это обновление блокировало только записи связанные с обновляемой группой, позволяя нормально работать со всеми остальными... это не защитит тебя от Insert-а. а триггер, мало того что он "транзакционно-зависим", только добавит времени выполнения. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:40 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpв идеале, мне хочется чтобы это обновление блокировало только записи связанные с обновляемой группой, позволяя нормально работать со всеми остальными... Если "группа" определяется значением FK ключа, то перед работой с ней обнови master-запись. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 17:46 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp, Мало выходных данных: акт вандализма разовый или периодически планируется? Влиять на "вне субдшную" логику/алгоритмы есть возможность? Падение производительности на время обновления критично? Если Да, то логично для группы ввести флаг активен/нет. Анализировать его на клиенте (?вьюхах/процедурах). Тогда задача обновления не будет столь критичной. Если нет, запрет реализуется через триггер: если на запись (группу?) выставлен флаг - запрет обновления, вставки данных. Основная цель: избежать длительной и большой транзакции. Цена: производительность ... |
|||
:
Нравится:
Не нравится:
|
|||
23.04.2018, 22:12 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Mikle83alekcvp, Мало выходных данных: акт вандализма разовый или периодически планируется? Влиять на "вне субдшную" логику/алгоритмы есть возможность? Падение производительности на время обновления критично? Если Да, то логично для группы ввести флаг активен/нет. Анализировать его на клиенте (?вьюхах/процедурах). Тогда задача обновления не будет столь критичной. Если нет, запрет реализуется через триггер: если на запись (группу?) выставлен флаг - запрет обновления, вставки данных. Основная цель: избежать длительной и большой транзакции. Цена: производительность 1. Разовый, но неоднократный, в смысле изредка возникает необходимость. 2. Есть, но не хотелось бы плодить сущности в виде дополнительных таблиц. К тому же это "псевдотрёхзвенка", т.е. приложение взаимодействует только с ХП. 3. Производительность вообще не критична, желательно чтобы во время обновления можно было получить доступ к незатронутым обновлением записям. Флаг - это хорошо, но если во время обновления приложение будет убито по какой-либо причине? Флаг в базе так и останется, группа станет недоступна и придётся лезть в базу "руками". ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 09:44 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpФлаг - это хорошо, но если во время обновления приложение будет убито по какой-либо причине? Флаг в базе так и останется Флаг - это запись. Если ее удалось удалить обновить - значит, это "зависший" флаг (создввшая его транзакция его не удалила). И как такое может быть, чтобы не было коммита, а флаг остался. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 11:13 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpФлаг - это хорошо, но если во время обновления приложение будет убито по какой-либо причине? Флаг в базе так и останется, группа станет недоступна и придётся лезть в базу "руками".В соседней теме Триггер на дисконнект. когда должен сработать? перетирали триггер на дисконнект, как раз для похожего случая. убиение приложения и сетевые обрывы закрывает вполне себе. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 12:30 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockalekcvpФлаг - это хорошо, но если во время обновления приложение будет убито по какой-либо причине? Флаг в базе так и останется Флаг - это запись. Если ее удалось удалить обновить - значит, это "зависший" флаг (создввшая его транзакция его не удалила). И как такое может быть, чтобы не было коммита, а флаг остался. А если он создаётся внутри обновляющей транзакции, то другие пользователи его всё равно не увидят до тех пор пока транзакция не завершится - он бесполезен. Поэтому его надо создавать вне основной рабочей транзакции, потом делать commit и только потом начинать обновление данных. В итоге сделал следующее: 1. Добавил в таблице групп поле grplock; 2. Когда пользователь запрашивает права на запись в эту группу, то это поле проверяется и если оно не null то он посылается; 3. Добавил ХП LOCK_GROUP(gid, locked), которая делает нехорошую вещь: Код: plsql 1. 2. 3. 4.
т.е. даже внутри транзакции она обновляет это поле и изменения видны всем. Если во время обновления данных произойдёт какой-либо exception, то она вызывается ещё раз с locked = 0, после чего транзакции делается rollback. 4. В дисконнект триггер добавил Код: plsql 1. 2.
P.S: Пишущая транзакция nowait. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 12:48 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpА если он создаётся внутри обновляющей транзакции, то другие пользователи его всё равно не увидят до тех пор пока транзакция не завершится - он бесполезен.Как раз увидят, если попытаются создать такую же запись. Или обновить существующую. UPDATE OR INSERT, например, упадет. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 12:52 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockalekcvpА если он создаётся внутри обновляющей транзакции, то другие пользователи его всё равно не увидят до тех пор пока транзакция не завершится - он бесполезен.Как раз увидят, если попытаются создать такую же запись. Или обновить существующую. UPDATE OR INSERT, например, упадет. Ага, только мне нужно чтобы они и в другие таблицы не могли добавлять записи, ссылающиеся на эту. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 12:54 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpАга, только мне нужно чтобы они и в другие таблицы не могли добавлять записи, ссылающиеся на эту.Ну правильно! Вначале добавляешь такой флаг, если получилось - делаешь все дальнейшие обновления по таблицам, если не получилось - полный отлуп. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 12:58 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpмне нужно чтобы они и в другие таблицы не могли добавлять записи, ссылающиеся на этуА, я понял. Ну сделай триггер в каждой такой таблице, который будет делать этот UPDATE OR INSERT флага. Ужас какой-то, конечно :) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:00 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockсделай триггер в каждой такой таблице, который будет делать этот UPDATE OR INSERT флагаУчти, в этом случае обновлять данные в этих таблицах сможет только одна транзакция. Смахивает на монопольное открытие dbf. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:02 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp1. Добавил в таблице групп поле grplock;Вынеси его в другую таблицу с контролем уникальности. Смог добавить флаг - можно работать. Не смог - занято. Чтобы проверять зомби - добавь туда же CONNECTION ID того, кто добавил флаг. Дальше рассказывать ? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:07 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
hvladalekcvp1. Добавил в таблице групп поле grplock;Вынеси его в другую таблицу с контролем уникальности. Смог добавить флаг - можно работать. Не смог - занято. Чтобы проверять зомби - добавь туда же CONNECTION ID того, кто добавил флаг. Дальше рассказывать ? 1. Зачем в таблицу уникальности? Он же к ID группы привязан, на другие группы не влияет, а в этой его обновить не смогут, потому что чтобы обновить надо права получить, а эта функция проверяет наличие этого флага. 2. Ну так и сделал, и в триггере на дисконнект его прибиваю. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:15 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockYuRockсделай триггер в каждой такой таблице, который будет делать этот UPDATE OR INSERT флагаУчти, в этом случае обновлять данные в этих таблицах сможет только одна транзакция. Смахивает на монопольное открытие dbf. Монопольное открытие можно и через lock_write сделать, мне это как раз и не нужно. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:16 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpЗачем в таблицу уникальности?Чтобы дважды не вставить один и тот же ID ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:23 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp2. Ну так и сделал, и в триггере на дисконнект его прибиваюТриггер на дисконнект может штатно не сработать. А вот транзакцию обязательно рано или поздно отпустит, что даст возможность другой транзакции (пере)установить этот флаг (в "таблице уникальности"). ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 13:30 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Использовать генератор для блокировки нежелательных изменений еще никто не предлагал? Взвели генератор - проапдейтили - сняли генератор . Для остальных проверка на триггере и Exception при необходимости. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 14:15 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvphvladпропущено... Вынеси его в другую таблицу с контролем уникальности. Смог добавить флаг - можно работать. Не смог - занято. Чтобы проверять зомби - добавь туда же CONNECTION ID того, кто добавил флаг. Дальше рассказывать ? 1. Зачем в таблицу уникальности? Он же к ID группы привязан, на другие группы не влияет, а в этой его обновить не смогут, потому что чтобы обновить надо права получить, а эта функция проверяет наличие этого флага. 2. Ну так и сделал, и в триггере на дисконнект его прибиваю. Не надо проверять наличие флага. Надо пытаться добавить флаг в табличку с констреинтом уникальности. Индексы живут вне контекста транзакций, поэтому ты гарантированно получишь отлуп при попытке добавить еще один флаг, даже если тебе запись с этим флагом не видна. Заодно решаются "проблемы" с падением приложения: транзакция автоматом откатится, флаг снова можно будет добавлять. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 14:19 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Stalk, очень плохое решение ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 14:20 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Котовасия, ты предлагаешь удерживать тр-цию, вставившую флаг, на всё время "блокировки". Не факт, что это приемлемо. Зависит от времени удержания "блокировки". alekcvp, надеюсь, ты понял, что значение флага == ID той группы записей, которую нужно "блокировать" ? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 14:23 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
hvladКотовасия, ты предлагаешь удерживать тр-цию, вставившую флаг, на всё время "блокировки". Не факт, что это приемлемо. Зависит от времени удержания "блокировки". ... Ну так у ТС в исходном топике: alekcvp...требуется обновить поле value в таблицах MEMBERS и RECORDS для некоторого id_grp. При этом они должны быть обновлены все разом, в одной транзакции ... - какие тут сомнения? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 14:37 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
hvladКотовасия, ты предлагаешь удерживать тр-цию, вставившую флаг, на всё время "блокировки". Не факт, что это приемлемо. Зависит от времени удержания "блокировки". Вся операция, требующая блокировки, всё равно должна в одной транзакции выполняться, так что почему бы и нет?.. hvladalekcvp, надеюсь, ты понял, что значение флага == ID той группы записей, которую нужно "блокировать" ?Ну это понятно, идея мне нравится. Но заводить для этого отдельную таблицу... FireBird 3 поддерживает временные таблицы (которые в базу не пишутся), доступные одновременно всем подключениям? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 17:26 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpFireBird 3 поддерживает временные таблицы (которые в базу не пишутся), доступные одновременно всем подключениям? нет конечно ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 17:29 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpНу, в идеале, мне хочется чтобы это обновление блокировало только записи связанные с обновляемой группой, позволяя нормально работать со всеми остальными... Пройдет пару лет, система станет мощнее, и потребуется двумя "исполнителями" одновременно пересчитывать и апдейтить записи для двух разных групп. Как бы ты не выбрал, надо заранее учитывать, что блокировок может быть несколько. *возможно* проще всего на какой-нибудь из столбцов повесить CHECK CONTRAINT, что grp_id этой записи отсутствует в таблице блокировок WHERE LOCK_TABLE.ATTACHMENT <> CURRENT_CONNECTION. И триггером On Disconnect ее чистить не забывать. Впрочем, это не убережёт от изменения самого grp_id если такое может случиться ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:00 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Stalk, генератор не масштабируется на одновременное обновления 2 и более групп разными исполнителями ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:03 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp...Но заводить для этого отдельную таблицу... Прикинь, всего лишь создаешь табличку - и все, задача решена... :) ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:04 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpНу это понятно, идея мне нравится. Но заводить для этого отдельную таблицу... Лучше завести ОДНУ лишнюю табличку и для блокировки добавлять ОДНУ строку в неё, чем переписывать ВСЕ строки целевой группы в твоей больше таблицы, даже если из всей группы ты потом только изменишь 1% записей. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:04 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockТриггер на дисконнект может штатно не сработать. Может, хотя и не часто. А вот триггер на коненкт сработает ;-) Лайфхак из серии "чем общаги девочек отличаются от общаг мальчиков" ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:07 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp Код: plsql 1.
alekcvp Код: plsql 1.
кто есть uid ? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:09 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpFireBird 3 поддерживает временные таблицы (которые в базу не пишутся), доступные одновременно всем подключениям? а если бы поддерживал? ты не хочешь создавать ещё одну обычную таблицу (со списоком блокировок), но без хочешь создать ещё одну необычную (временную) таблицу? а в чем разница? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:11 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpЕсли во время обновления данных произойдёт какой-либо exception, то она вызывается ещё раз с locked = 0, после чего транзакции делается rollback. зачем? Анекдот про два стакана на ночь у постели программиста? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:14 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpВся операция, требующая блокировки, всё равно должна в одной транзакции выполняться Но сама блокировка может выполняться предварительно, в отдельной транзакции (если через флаги, в отдельной таблице или в отдельном столбце). alekcvpЕсли в этот момент какой-то пользователь изменит запись или добавит новую в таблицу RECORDS с этим же id_grp (читать можно), то процесс придётся начинать сначала. Вот это была мотивация или требование? Что должно произойти, если пока мы рассчитываем группу №1 другое соединение пытается удалить или изменить или добавить строку в этой же группе? Возможно, некоторые столбцы всё же можно изменять. Возможно, изменяющего клиента нужно сразу послать. Возможно, надо наоборот экстренно прервать процесс обновления. POST_EVENT и rollback, например. Возможно, надо учитывать как давно или скуолько раз обновление уже откладывалось. Типа до получаса разрешаем так прерывать обновление, а потом начинаем отказывать изменяющим клиентам и принудительно доводим перересчёт до конца. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 18:20 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
AriochalekcvpНу, в идеале, мне хочется чтобы это обновление блокировало только записи связанные с обновляемой группой, позволяя нормально работать со всеми остальными... Пройдет пару лет, система станет мощнее, и потребуется двумя "исполнителями" одновременно пересчитывать и апдейтить записи для двух разных групп. Не пройдёт, это "технический" процесс и он запускается не пользователями. Да и приложение не корпоративного масштаба, так - внутренний софт на один отдел. Завтра действительно попробую вариант с отдельной таблицей... ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 19:47 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
AriochalekcvpНу это понятно, идея мне нравится. Но заводить для этого отдельную таблицу... Лучше завести ОДНУ лишнюю табличку и для блокировки добавлять ОДНУ строку в неё, чем переписывать ВСЕ строки целевой группы в твоей больше таблицы, даже если из всей группы ты потом только изменишь 1% записей.Сейчас я завёл ОДНО ПОЛЕ в таблице групп и делаю ДВУКРАТНУЮ запись в него на каждый процесс. А в варианте с отдельной таблицей, в неё будут записи (попытки записей) при КАЖДОМ изменении данных в ТРЁХ таблицах. Плюс в моём варианте [если возникнет необходимость] можно проверить блокировку даже из read_commited транзакции и не дать прочитать данные из обновляемой группы. В случае отдельной таблицы с попыткой записи - так не получится. Ariochкто есть uid ?ID пользователя в таблице пользователей в базе. Т.е. поставить блокировку может кто угодно из тех кто имеет право писать в эти таблицы, а снять - только тот кто поставил. Ну и при дисконнекте по этому значению снимаются блокировки. AriochalekcvpFireBird 3 поддерживает временные таблицы (которые в базу не пишутся), доступные одновременно всем подключениям? а если бы поддерживал? ты не хочешь создавать ещё одну обычную таблицу (со списоком блокировок), но без хочешь создать ещё одну необычную (временную) таблицу? а в чем разница?В том, что при [аварийном] выключении сервера и при backup/restore не надо париться об этой таблице. AriochalekcvpЕсли во время обновления данных произойдёт какой-либо exception, то она вызывается ещё раз с locked = 0, после чего транзакции делается rollback. зачем? Анекдот про два стакана на ночь у постели программиста?Я же показал - там внутри автономная транзакция, которая в любом случае снимает блокировку, а rollback основной транзакции отменяет изменения, которые уже успел сделать "вывалившийся" процесс. AriochalekcvpВся операция, требующая блокировки, всё равно должна в одной транзакции выполняться Но сама блокировка может выполняться предварительно, в отдельной транзакции (если через флаги, в отдельной таблице или в отдельном столбце). Может и так. Но мне проще всё "завернуть" в одну транзакцию. AriochalekcvpЕсли в этот момент какой-то пользователь изменит запись или добавит новую в таблицу RECORDS с этим же id_grp (читать можно), то процесс придётся начинать сначала. Вот это была мотивация или требование? Что должно произойти, если пока мы рассчитываем группу №1 другое соединение пытается удалить или изменить или добавить строку в этой же группе?Ну представьте что там в записях электронные подписи, а в мемберсах - ключи для проверки. Что будет, если при смене этих подписей, кто-то добавит ещё одну запись, подписанную старым ключём (который считывается непосредственно перед подписью)? Если же обновлять сначала ключ, а потом подписи (в разных транзакциях), то кто-то в этот момент может попытаться проверить старую подпись новым ключём и будет облом. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:04 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvp, а что, старый и новый ключ не могут перекрываться по датам? Так ведь и происходит. я получаю новый ключ заранее, до окончания старого. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:14 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpСейчас я завёл ОДНО ПОЛЕ в таблице групп и делаю ДВУКРАТНУЮ запись в него на каждый процесс. А в варианте с отдельной таблицей, в неё будут записи (попытки записей) при КАЖДОМ изменении данных в ТРЁХ таблицах.Ну и зря. Так тебе нужно обновлять миллион записей (реальных данных, с возможно еще какими-то триггерами, индексами) два раза по неизвестно какому условию. А в случае таблицы локов - один раз, и еще миллион раз - обновлять одну запись с одним полем по ключу в короткой таблице. Что намного быстрее. К тому же, твой вариант поможет только при обновлении данных, а таблицу локов можно использовать, если нужно, и для insert/delete. alekcvpПлюс в моём варианте [если возникнет необходимость] можно проверить блокировку даже из read_commited транзакции и не дать прочитать данные из обновляемой группы. В случае отдельной таблицы с попыткой записи - так не получится.Транзакция любого типа может прочитать только закоммиченные данные. Так у тебя одна транзакция, или две? Или ты после первого update делаешь CommitRetaining? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:21 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpID пользователя в таблице пользователей в базе. Т.е. поставить блокировку может кто угодно из тех кто имеет право писать в эти таблицы, а снять - только тот кто поставил. Ну и при дисконнекте по этому значению снимаются блокировки. а если клиент отвалился без отрабатывания триггера? как, например, любому другому клиенту в триггере on connect определить, что пользователя Х остались бесхозные блокировки и снять их ? Also, если расчёты идут так долго, то как часто клиент общается с сервером? 1. рассчитывает строку, записывает её в сервер (update), рассчитывает следующую, записывает, в конце - commit 2. долго рассчитывает все строки, потом все сразу сливает на сервер и commit, во время самих рассчетов с сервером не общается alekcvpВ том, что при [аварийном] выключении сервера и при backup/restore не надо париться об этой таблице. On connect триггер, зачищающий блокировки, IMHO все равно желателен. alekcvpМожет и так. Но мне проще всё "завернуть" в одну транзакцию. у тебя автономные транзакции летают - это уже едва ли "в одну" alekcvpавтономная транзакция, которая в любом случае снимает блокировку > Because the autonomous transaction is completely independent of its parent, care must be taken to avoid deadlocks. В официальных примерах они используются только, чтобы добавлять записи в лог-таблицы. У меня сильные сомнения, что есть какие-то гарантии по синхронизации. Т.е. я не вижу принципиальной невозможности такой последовательности: 1. запускается транзакция на установку блокировки, но почему-либо притормаживается. Sweep пошёл тяжелый, или встала ждёт строку, модифицированную незакомиченной другой транзакцией 2. выполняются изменение данных и запускается автономка для снятия лока 3. 2-я автономка завершается, лок снят 4. 1-я автономка "отмерзает" завершается, лок выставлен Я бы очень подумал, прежде чем с блокировками работать асинхронными средствами. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:33 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpМожет и так. Но мне проще всё "завернуть" в одну транзакцию. дело не в том, что проще, а в том какого конкретно детерминированного поведения ты хочешь джобиться, в случае конфликта - 21365634 !!! Вот тебе ещё на вскидку асинхронный сценарий. 1. ты из соединения 1 начал редактировать записи по группе 1, 2. начинает создаваться автономка №1 для выставления лока 3. пересчитывается и изменяется одна строка данных по группе 1 4. ты из соединения 2 редактируешь САМУ ГРУППУ 1, меняешь ей название например, но еще не коммитишь 5. автономка №1 начинает исполняться, обнаруживает, что запись группы была изменена из соединения 2 и по конфликту умирает с роллбаком. 6. соединение 2 коммитит переименование группы 7. пересчитывается и изменяется 2-я строка данных по группе 1 8. пересчитывается и изменяется 3-я строка данных по группе 1 ....и т.д., изменения данных пошли, а лок не выставлен. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:38 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpНу представьте что там в записях электронные подписи, а в мемберсах - ключи для проверки. я не хочу представлять и гадать, я хочу чтобы вы чётко сформулировали как в такой ситуации должна правильно вести себя ваша система. Какие варианты ее поведения желательны, какие нежелательны, но допустимы, и какие недопустимы категорически. после того, как вы сформулируете четко поведение, "дизайн", можно обсуждать как такую "архитектуру" лучше закодировать. но кодировать неизвестное несформулированное поведение - это с ненулевой вероятностью получить программу качества GIGO ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:42 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockТак тебе нужно обновлять миллион записей нет, не так. он добавил столбец - НЕ В ТАБЛИЦУ ДАННЫХ, а в отдельные "справочник групп" "миллионы записей" он меняет в таблицах MEMBERS и RECORDS а "выставляет флаг" в таблице GROUPS во всяком случае я так его понял PS. "обновлять два раза" возможно не так уж и плохо, если обновляются ВСЕ строки конкретной группы. Во всяком случае это не хуже, чем SELECT fOR UPDATE Вот если бы он обновлял для блокировки миллион строк ,а потом реально вносил изменения данных в тысячу из них - тогда да, жуткий перерасход записей. Но если обновление тотальное - то двукратное или даже трекратное умножение записей вполне могло бы быть терпимым ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:49 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRockalekcvpСейчас я завёл ОДНО ПОЛЕ в таблице групп и делаю ДВУКРАТНУЮ запись в него на каждый процесс. А в варианте с отдельной таблицей, в неё будут записи (попытки записей) при КАЖДОМ изменении данных в ТРЁХ таблицах.Ну и зря. Так тебе нужно обновлять миллион записей (реальных данных, с возможно еще какими-то триггерами, индексами) два разаО, я недочитал. Раз ты только "таблицу групп" дважды обновляешь - значит, это изменение "на клиенте" в логике. Значит, раз этого достаточно, можно и запись в таблицу локов один раз делать, а не в триггерах. Впрочем, это не важно, раз достаточно. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:50 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Ariochнет, не так. он добавил столбец - НЕ В ТАБЛИЦУ ДАННЫХ, а в отдельные "справочник групп"Да, я уже сам заметил. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:51 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
YuRock, ну он просто объединил таблицу локов и таблицу-справочник групп воедино если она не слишком широкая и сама по себе не часто меняется, то и нехай себе ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:51 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
.....только нахрена же автономки тут. Блокировки всегда делаются, чтобы принудительно и гарантировано сериализовать(синхронизировать) принципиально асинхронные (параллельные, хаотические по времени начала) операции. А он пытается одни асинхронные операции сериализовать другими асинхронными. Ну в большинстве случаев это сработает, конечно, не вопрос. Всё таки БД на диске - не многоядерный процессор. Но изредка гейзенбаги скорее всего будут случаться. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:53 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
AriochВот тебе ещё на вскидку асинхронный сценарий.Я правильно тебя понял, что в твоём "асинхронном сценарии" основная и автономные тр-ции выполняются параллельно ? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 20:57 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
kdvalekcvp, а что, старый и новый ключ не могут перекрываться по датам? Так ведь и происходит. я получаю новый ключ заранее, до окончания старого.Это был пример для понимания, а не реальная ситуация. По факту там цифровые конверты - ключи в members и сами данные в records. Процесс обновления вызывается когда у кого-то отзывается доступ к группе, для смены ключей. YuRockalekcvpПлюс в моём варианте [если возникнет необходимость] можно проверить блокировку даже из read_commited транзакции и не дать прочитать данные из обновляемой группы. В случае отдельной таблицы с попыткой записи - так не получится.Транзакция любого типа может прочитать только закоммиченные данные. Так у тебя одна транзакция, или две? Или ты после первого update делаешь CommitRetaining? У меня две транзакции. И проверить значение lock-поля в таблице групп я могу и из читающей, а чтобы попробовать что-то записать в отдельную таблицу и узнать получится или нет - мне придётся обязательно стартовать и пишущую. AriochalekcvpID пользователя в таблице пользователей в базе. Т.е. поставить блокировку может кто угодно из тех кто имеет право писать в эти таблицы, а снять - только тот кто поставил. Ну и при дисконнекте по этому значению снимаются блокировки.а если клиент отвалился без отрабатывания триггера?Пока думаю над этим, но возможно заставлю ту процедуру, которая проверяет его наличие, проверять (опять же при состоянии locked = 1) так же наличие активной сессии заблокированного пользователя. Ну или перейду на вариант с отдельной таблицей - у обоих вариантов есть свои плюсы и минусы. AriochAlso, если расчёты идут так долго, то как часто клиент общается с сервером?Хм, мне казалось что я написал: считывает строку, обрабатывает (~10 секунд), запихивает назад. AriochalekcvpМожет и так. Но мне проще всё "завернуть" в одну транзакцию. у тебя автономные транзакции летают - это уже едва ли "в одну" В одну с точки зрения приложения, что там в базе происходит - приложению знать не обязательно. AriochЯ бы очень подумал, прежде чем с блокировками работать асинхронными средствами.Там же написано что автономная транзакция наследует параметры "родительской", родительская - nowait, т.е. либо обновила сразу, либо вывалилась с ошибкой. Или я как-то не так понимаю механизм nowait-транзакций (тоже вариант)? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.04.2018, 21:34 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
hvladЯ правильно тебя понял, что в твоём "асинхронном сценарии" основная и автономные тр-ции выполняются параллельно ? могут выполняться параллельно. в доках не указаны никакие гарантии синхронизации, стало быть это деталь реализации и сервер может делать так, как ему будет удобнее. В зависимости от содержимого базы ,настроек, версии сервера и фазы луны. закладываться на то, что не имеет никаких гарантий и может при любом изменении данных или версий рассыпаться, да еще "в многопотоке" с его трудностями воспроизводимой диагностики - я бы не стал. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 12:14 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpТам же написано что автономная транзакция наследует параметры "родительской" там во-первых НЕ написано, что родительская транзакция встанет торчком и будет ждать окончания автономки. Она запустит процесс создания и выполнения автономки, но когда та закончится и закоммититься - детали реализации. Для ведения логов это подходит, если у тебя запись в лог внесется на несколько секунд позже, чем данные, не важно, лишь бы внеслась. Для синхронизации многопотока - на мой взгляд это раскладывание граблей. И во вторых там НЕ написано, что родительская транзакция проверит результат автономки. Я в твоем описании не заметил, что если 1-я автономка отвалится и не сможет выставить лок - то дальше процесс остановится. Поэтому на мой вкус - лучше честно-примитивно делать две транзакции. а) выставление лока, commit. Теперь приложение точно знает, что лок выставлен. Или что была ошибка. б) изменение данных и снятие лока, commit; в) и вообще, тогда ЛЮБЫЕ изменения данных, разумеется, должны делаться через локи. Не только большой-перерасчёт, но и любые. Чтобы не было картинки 1) соединение 1 хочет внести небольшие изменения в несколько строк данных по группе 1. Оно открывает транзакцию (RC? snapshot?), проверяет что лока нет (массовый перерасчет не идёт) и начинает изменять свои пару сотен строчек. 2) соединение 2 хочет начать массовый перерасчет и выставляет лок 3) соединение 1 продолжает изменять данные, потому что лок проверялся раньше и тогда его не было 4) соединение 2 тоже изменяет данные, но поскольку рассчёты большие и массивные - делает это медлено. .....а дальше кто первый закоммитится, скорее всего 1-е. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 12:23 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
AriochhvladЯ правильно тебя понял, что в твоём "асинхронном сценарии" основная и автономные тр-ции выполняются параллельно ? могут выполняться параллельно. в доках не указаны никакие гарантии синхронизацииВ документации не обязаны описывать чьи-то фантазии. Раз и навсегда - автономные тр-ции выполняются в том же логическом потоке управления, что и весь остальной код пользователя. Если вдруг когда то появится *внутренняя* параллельность при выполнения запросов, то код пользователя никак об этом не узнает. Разве что косвенно, по статистике\плану. Но с точки зрения пользователя - это один логический поток управления. Без спецэффектов. Ещё раз: тр-ция не является самостоятельным элементом выполнения кода. Это просто характеристика текущего окружения, она не может "выполнять" запросы. Это скорее контекст выполнения, а не само выполнение. PS Выдыхай уже ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 13:42 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
AriochalekcvpТам же написано что автономная транзакция наследует параметры "родительской" там во-первых НЕ написано, что родительская транзакция встанет торчком и будет ждать окончания автономки. Это логически ожидаемо. Иначе можно сказать что нельзя писать хранимки с таким кодом: Код: plsql 1. 2.
Т.к. никто не гарантирует, что на момент insert'a select уже выполнится. Что звучит как полный бред. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 13:59 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
alekcvpнельзя писать хранимки, Т.к. никто не гарантирует FB documentationThe body of a PSQL module is a block of statements that run in a logical sequence, like a program. Это во первых. А во вторых, твой стейтмент выполнился - автономная транзакция запущена. Остальное - детали реализации. hvladВ документации не обязаны описывать чьи-то фантазии. да вообще никто никому ничего не обязан. и завязывать критический код на никому не обещанные детали реализации конечно же можно. а если потом реализация будет оптимизирована - "так это, пойми, потом". В общем, просто делаем на этом форуме поиск фразы "не обещал", читаем, потом думаем кто будет искать гейзенбаги в многопоточном коде лет через несколько, и выбираем. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 15:35 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Arioch, у тебя явная неспособность оценить уровень собственных фантазмов :) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 15:44 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Ariochalekcvpнельзя писать хранимки, Т.к. никто не гарантирует FB documentationThe body of a PSQL module is a block of statements that run in a logical sequence, like a program. Это во первых. А во вторых, твой стейтмент выполнился - автономная транзакция запущена. Остальное - детали реализации. Именно. "block of statements that run in a logical sequence". Т.е. в любой точке хранимки я могу быть уверен, что весь предыдущий код (с учётом ветвлений) уже выполнился, вне зависимости от того в автономной он транзакции или нет. Или с циклами for такая же фигня - он запустился на исполнение, а когда закончится - никто не знает, хранимка дальше пошла?.. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 16:02 |
|
Массовое обновление данных в базе
|
|||
---|---|---|---|
#18+
Это уже не трава пошла... ... |
|||
:
Нравится:
Не нравится:
|
|||
25.04.2018, 17:58 |
|
|
start [/forum/topic.php?all=1&fid=40&tid=1561139]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
35ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
86ms |
get tp. blocked users: |
1ms |
others: | 12ms |
total: | 170ms |
0 / 0 |