powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вопрос по самообразованию
17 сообщений из 17, страница 1 из 1
вопрос по самообразованию
    #34207473
Драга
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
собственно, вот код взятый из доки по Pg

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
-- Insert or update the summary row with the new values.
        <<insert_update>>
        LOOP
            UPDATE sales_summary_bytime
                SET amount_sold = amount_sold + delta_amount_sold,
                    units_sold = units_sold + delta_units_sold,
                    amount_cost = amount_cost + delta_amount_cost
                WHERE time_key = delta_time_key;

            EXIT insert_update WHEN found;    

            BEGIN
                INSERT INTO sales_summary_bytime (
                            time_key, 
                            amount_sold, 
                            units_sold, 
                            amount_cost)
                    VALUES ( 
                            delta_time_key,
                            delta_amount_sold,
                            delta_units_sold,
                            delta_amount_cost
                           );

                EXIT insert_update;

            EXCEPTION
                WHEN UNIQUE_VIOLATION THEN
                    -- do nothing
            END;
        END LOOP insert_update;

Вопрос, зачем все это делается в цикле?
Каким образом он вообще может отработать в цикле, как я понимаю пытаемся проделать update, если не получилось делаем insert, как он может сгенерить ошибку unique_violation, если update перед ним не отработал?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34207767
СергейК
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ia tak ponimau, chto eto delaetsia radi ispolzovania metki. Tak kak v chistom PL/pgSQL metok net. A u tsiklov est' metki v kontse.

A otlov oshibki unique_violation tut toje po delu stoit. Na sluchai esli pervyy UPDATE zavershitsia s takoi oshibkoi -- delo v tom chto etot otlov oshibki otnositsia NE k poslednemu INSERT'u, a ko vsemu bloku!
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34207783
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
блок exception является необязательной частью блока begin end; и в данном случае обрабатывает некорректный инсерт. а насчет того, откуда исключение, так ведь этот код может работать в нескольких сессиях. Между update и insert может произойти вставка в другой сессии с таким же delta_time_key
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34209380
Фотография Misha Tyurin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДрагаВопрос, зачем все это делается в цикле?
СергейК...Tak kak v chistom PL/pgSQL metok net. A u tsiklov est' metki v kontse...

Я понимаю так: чтобы изменения применились в любом случае.
Метки тут ни при чём.

Предполагается, что возможен вариант:

* в момент апдейта там небыло такого объекта (с таким ключём),
* а перед тем как интсертиться он уже появился (где-то паралельно успелось вставиться); -

но при этом надо в любом случае произветси либо вставку, либо апдейт

* тогда по циклу переходим снова на апдейт и т. д. пока либо не проапдейтим, либо не вставим.
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34209584
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Misha Tyurin Я понимаю так: чтобы изменения применились в любом случае.
Метки тут ни при чём.

Предполагается, что возможен вариант:

* в момент апдейта там небыло такого объекта (с таким ключём),
* а перед тем как интсертиться он уже появился (где-то паралельно успелось вставиться); -

но при этом надо в любом случае произветси либо вставку, либо апдейт

* тогда по циклу переходим снова на апдейт и т. д. пока либо не проапдейтим, либо не вставим.наскоко я понимаю, это код на PL/pgSQL , т.е. он весь унутре одной процедуры ==> одной транзакции.
Не подскажите, какой должен быть установлен уровень изоляции, чтобы разные стейтменты внутри транзакции (вернее - одни и те же, но в разное время) видели разные данные, измененные другими транзакциями за время отработки текущей. А в каком случае транзакция вывалится по бесконечному цыклу (и вывалится ли).
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34209988
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если уровень не Serializable, то разные операторы одной транзакции вполне могут увидеть разные данные, которая зафиксировала другая транзакция.
или я не прав?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210011
.gc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
.gc
Гость
Код триггера в первом посте взят из http://developer.postgresql.org/pgdocs/postgres/plpgsql-trigger.html

Создаем таблицы и триггер, запускаем две консоли psql (#1, #2)
(PostgreSQL 8.1.4 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5))
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
# 1 . BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
       # 2 . BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;
# 1 . INSERT INTO sales_fact VALUES( 1 , 1 , 1 , 10 , 3 , 15 );
# 1 . INSERT INTO sales_fact VALUES( 1 , 2 , 1 , 20 , 5 , 35 );
# 1 . INSERT INTO sales_fact VALUES( 2 , 2 , 1 , 40 , 15 , 135 );
      # 2 . INSERT INTO sales_fact VALUES( 2 , 3 , 1 , 10 , 1 , 13 ); -- тут сеанс тихо подвисает в ожидании
# 1 . COMMIT; -- OK
      # 2 . --- висит и жадно отжирает всю память :(
это в случае, если sales_summary_bytime была пустая, если там были записи, то вторая транзакция отваливается:
Код: plaintext
1.
2.
3.
ERROR:  could not serialize access due to concurrent update
CONTEXT:  SQL statement "UPDATE sales_summary_bytime ....
PL/pgSQL function "maint_sales_summary_bytime" line  43  at SQL statement
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210084
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
st_sergЕсли уровень не Serializable, то разные операторы одной транзакции вполне могут увидеть разные данные, которая зафиксировала другая транзакция.
или я не прав?Вы правы. Особо, если учесть что единственным уровнем кроме Serializable в посгре является READ COMMITTED (умолчательный).

однако, поскольку мы (кажется) не можем (или я не прав?) порулить уровнем изоляции внутри процедуры (в данном случае - триггерной) - т.к. она заведомо выполняется внутри вызвавшей транзакции, то данное решение не устойчиво относительно выбора уровня изоляции (применив данное решение мы отказываем себе в удовольствии выполнять что-либо, затрагивающее данный триггер в режиме Serializable. Т.к. при конкуренции, приведшей к закольцовыванию цыкла, транзакция кажется повиснет в вечном лупе. Или таки вывалится с эксепшеном (что вряд ли - это ж не рекурсия, где ресурсы исчерпываются приводя к явной ошибке, а обычный цыкл) и ее придется рубить снаружи? Нет?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210101
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
postgres=# select version();
                                         version
------------------------------------------------------------------------------------------
 PostgreSQL  8 . 2 . 0  on i686-pc-mingw32, compiled by GCC gcc.exe (GCC)  3 . 4 . 2  (mingw-special)
проверил пост .gc, у меня в любом случае вываливается exception
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210181
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
st_serg
Код: plaintext
1.
2.
3.
4.
postgres=# select version();
                                         version
------------------------------------------------------------------------------------------
 PostgreSQL  8 . 2 . 0  on i686-pc-mingw32, compiled by GCC gcc.exe (GCC)  3 . 4 . 2  (mingw-special)
проверил пост .gc, у меня в любом случае вываливается exception
1/ на пустых таблицах:

ERROR: out of memory
DETAIL: Failed on request of size 20.
CONTEXT: SQL statement "UPDATE sales_summary_bytime SET amount_sold = amount_sold + $1 , units_sold = units_sold + $2 , amount_cost = amount_cost + $3 WHERE time_key = $4 "
PL/pgSQL function "maint_sales_summary_bytime" line 43 at SQL statement

2/ на имеющих записи

ERROR: could not serialize access due to concurrent update
CONTEXT: SQL statement "UPDATE sales_summary_bytime SET amount_sold = amount_sold + $1 , units_sold = units_sold + $2 , amount_cost = amount_cost + $3 WHERE time_key = $4 "
PL/pgSQL function "maint_sales_summary_bytime" line 43 at SQL statement
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210188
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а версия пг?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210211
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ага, сори, мой косяк )
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210213
4321
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
st_sergа версия пг?
Код: plaintext
"PostgreSQL 8.1.2 on i386-unknown-freebsd5.4, compiled by GCC gcc (GCC) 3.4.2 [FreeBSD] 20040728"


зы. про пг 8.2.0 было что-то непотребное сказано на сравнении БД. Про сложные запросы. Как у вас?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210247
Драга
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код действительно взять из триггерной функции, забыл указать.

Вопрос, по крайней мере для меня, так и остался не проясненным. Этот код - руководство к действию и правильно писать именно так?
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210249
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я работаю с oracle, а за пг просто наблюдаю, интересно... так что про сложные запросы ничего сказать не могу.
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210285
st_serg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДрагаКод действительно взять из триггерной функции, забыл указать.

Вопрос, по крайней мере для меня, так и остался не проясненным. Этот код - руководство к действию и правильно писать именно так?
на уровне изоляции serializable этот код не всегда будет работать
в триггерной функции поменяйте блок
Код: plaintext
1.
2.
3.
EXCEPTION
                WHEN UNIQUE_VIOLATION THEN
                    -- do nothing
на
Код: plaintext
1.
2.
3.
EXCEPTION
                WHEN UNIQUE_VIOLATION THEN
                    raise notice 'UNIQUE_VIOLATION';
выполните пример, который написал .gc, и посмотрите что получиться
...
Рейтинг: 0 / 0
вопрос по самообразованию
    #34210540
.gc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
.gc
Гость
Драга Этот код - руководство к действию и правильно писать именно так?
учитывая скрытые неприятные "сюрпризы" с этим кодом, которые проявляются при определенных условиях (хоть возможно и маловероятных), можно, например, добавить счетчик неуспешных проходов цикла и отваливаться с exception по превышению допустимого числа попыток :)

btw, решить часть проблем с UPDATE or INSERT в режиме SERIALIZABLE могут явные блокировки таблиц на время транзакции.
...
Рейтинг: 0 / 0
17 сообщений из 17, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вопрос по самообразованию
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]