172 похожих чатов

Кто-То может подсказать как можно сделать атомарно вот такую вещь? UPDATE

users SET balance=(SELECT SUM(amount) FROM transactions WHERE user_id=?)
Я же верно понимаю, что тут 2 запроса и если кто-то удалил параллельно из таблицы транзакций после того как в этом запросе посчиталась сумма, то я сохраню невалидный баланс.
Кроме блокировок можно это решить? Я знаю, что если мы будем запускать перерасчет после каждой операции изменения в таблицы transactions, то получим eventual consistency и баланс так или иначе будет верный. Мне бы понять можно ли просто запросом sql такой кейс решить

15 ответов

8 просмотров

Это будет в рамках одной транзакции, поэтому вы получите валидный результат на отметку времени начала транзакции. Если вы после каждого изменения таблицы transactions гарантированно выполняете такой запрос, то и баланс будет актуальный.

А как Вы собираетесь поддерживать в валидном состоянии баланс, если только не из приложения?

Кстати, почему бы не использовать триггеры на таблице transactions, которые будут автоматически обновлять поле balance в таблице users ? В случае триггеров счётчик не должен сбиваться.

Andrei Ilinskii
Кстати, почему бы не использовать триггеры на табл...

Вообще я бы через CTE соединил запросы вставки новых данных в transactions и обновление счётчика, чтобы не усложнять структуру базы.

Evgeny-Kungurov Автор вопроса
Andrei Ilinskii
Кстати, почему бы не использовать триггеры на табл...

Я ниразу их не юзал. Я разработчик который постоянно сталкивается с подобными вещами и кроме блокировок мне ничего на ум не приходит. Другие разработчики +- так же отвечают. Решил спросить у тех, кто хорошо в БД шарит

Evgeny Kungurov
Я ниразу их не юзал. Я разработчик который постоян...

Давай без триггеров вариант с CTE посмотрим. WITH data(user_id, amount) AS ( -- входящие параметры SELECT :user_id, :amount ), insert AS ( INSERT INTO transactions SELECT * FROM data ) UPDATE users SET balance = balance + data.amount FROM data WHERE users.user_id = data.user_id Чем не нравится?

Evgeny Kungurov
Надо обмозговать)

С триггерами по-сути тоже самое будет, просто часть с update уедет в триггер. Если задача держать поле balance в постоянном соответствии с суммой amount по таблице transactions, то вставка в транзакции и обновление счётчика должны идти в одной транзакции, по очевидным причинам )

Запросы всегда работают атомарно, а Вам тут нужно изоляция. К примеру, на уровне изоляции serializable это делается тривиально. Понятия "после / до" для параллельных транзакций не имеют прямого отношения к consistency, кстати.

Andrei Ilinskii
Кстати, почему бы не использовать триггеры на табл...

В триггерах нет никакой "магии", если Вы об этом. Т.е. если процедура обновления баланса ненадёжна сама по себе, и в триггере она будет работать не лучше.

Она и так атомарная. Баланс в любом случае на какой-то момент будет валидным -- и перестанет быть валидным сразу после этого момента. Более того, время, в течение которого этот баланс был валидным -- можэт быть строго 0, что не отменяет того, что значение поля balance после коммита соответствует балансу на какой-то момент в прошлом. Вопрос как сделать, чтобы этот баланс не менялся -- это другой вопрос. И ключевое здесь -- сколько вы хотите чтобы он не менялся и зачем вам это нужно.

Evgeny Kungurov
Я ниразу их не юзал. Я разработчик который постоян...

Если Вам важен результат этих транзакций — почитали бы Вы какой-то "фундаментальный" учебник про основные принципы ACID, честное слово. А то потом приходится (лично мне много приходилось) искать косяки в транзакциях и как-то устранять "кашу" в БД после "блокировщиков". ;(

Evgeny-Kungurov Автор вопроса
Yaroslav Schekin
Если Вам важен результат этих транзакций — почитал...

Есть пример? А то тонна инфы в инете, а толку не так много для меня. Я тоже знаю много разработчиков, у которых есть в компании DBA, который потом всем пальчиком показывает, но у меня нет такого спеца.

Evgeny Kungurov
Есть пример? А то тонна инфы в инете, а толку не т...

Пример учебника, в смысле? Я сходу не помню... ну вот "Database system concepts", например. > у которых есть в компании DBA Заниматься такими вещами — вообще не дело DataBase Administrator. Это базовые знания, умения и ответственность разработчика баз данных, если что. ;)

Andrei Ilinskii
Давай без триггеров вариант с CTE посмотрим. WITH ...

> и изоляция там по умолчанию read_commited. Значит, см. вариант 2. > Меня лишь интересовало как сделать без блокировок сделать правильные цифры. Пути, показанные тут https://t.me/pgsql/346283 и тут https://t.me/pgsql/346286 (если "..." заполнить аналогично первому примеру), на первый взгляд верные. Это если считать, что других (пишущих) транзакций, затрагивающих эту таблицу, в базе не бывает (взаимодействия с ними нужно разбирать отдельно). Собственно, это ещё одна проблема RC в нетривиальных случаях — для добавления ещё одного вида транзакции в худшем случае придётся подумать, как она будет взаимодействовать с N уже существующих. > Вот первая статья Да не читайте Вы эту чушь "статьи" (почти все те, что я в когда-либо видел, содержали грубые ошибки, например) — читайте учебники и документацию.

Похожие вопросы

Обсуждают сегодня

Всем привет, написал код ниже, но он выдает сегфолт, в чем причина? #include <stdio.h> #include <stdlib.h> #include <string.h> struct product { char *name; float price; };...
buzz базз
60
Хотел бы спросить у знающих, правильную ли я выбрал книгу для начала изучения ассемблера Юрова В.И ? Или есть более лучшие книги для начала обучения?
Botsman
25
Книга Юрова В.И пойдёт для обучения?
Botsman
24
$params = [ 'formid' => 'feedbackForm', 'formTpl' => '@CODE: <form class="form-validate" data-id="ajax_form"> <fieldset class="margin-bottom-md"> ...
Pathologic
1
> Примечательно, что новый владелец удаляет из GitHub любые жалобы, указывающие на подозрительную активность или смену владельца, и, видимо, рассчитывает на то, что пользовате...
Alex Sherbakov
1
Hey there Which is the best Linux destro for developers (coding)? To my research on reddit, they said Linux mint is good for mid level spec and Ubuntu for high Lev hardwar...
Wiz 🪄
11
Подскажите пожалуйста, а я могу вот такую штуку использовать? rpc, только реализованное в реббите https://www.rabbitmq.com/tutorials/tutorial-six-php ( или https://habr.com/ru...
Artyom
11
И ещё вопрос: можно ли типа как на дос как-то запариться и с помощью прерываний выводить текст, вместо функции printf ?
НѣкъиⰘижєжєиꙁъвьсєсвѣтьноѣсѣтиѥсть•
34
а мы ещё не созрели до того, чтобы создать отдельный чатик про настройку редакторов?
Cheese Syrowiecki
16
Всем привет! У меня почему-то по-разному отображается TListView в Debug и Release режимах (FireMonkey)! При запуске под Win приложения TListView заливается программо. в Debug ...
Александр COM
8
Карта сайта