Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / вопрос по самообразованию / 17 сообщений из 17, страница 1 из 1
18.12.2006, 14:20
    #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
18.12.2006, 15:40
    #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
18.12.2006, 15:43
    #34207783
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
блок exception является необязательной частью блока begin end; и в данном случае обрабатывает некорректный инсерт. а насчет того, откуда исключение, так ведь этот код может работать в нескольких сессиях. Между update и insert может произойти вставка в другой сессии с таким же delta_time_key
...
Рейтинг: 0 / 0
19.12.2006, 09:28
    #34209380
Misha Tyurin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
ДрагаВопрос, зачем все это делается в цикле?
СергейК...Tak kak v chistom PL/pgSQL metok net. A u tsiklov est' metki v kontse...

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

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

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

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

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

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

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

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

* тогда по циклу переходим снова на апдейт и т. д. пока либо не проапдейтим, либо не вставим.наскоко я понимаю, это код на PL/pgSQL , т.е. он весь унутре одной процедуры ==> одной транзакции.
Не подскажите, какой должен быть установлен уровень изоляции, чтобы разные стейтменты внутри транзакции (вернее - одни и те же, но в разное время) видели разные данные, измененные другими транзакциями за время отработки текущей. А в каком случае транзакция вывалится по бесконечному цыклу (и вывалится ли).
...
Рейтинг: 0 / 0
19.12.2006, 12:08
    #34209988
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
Если уровень не Serializable, то разные операторы одной транзакции вполне могут увидеть разные данные, которая зафиксировала другая транзакция.
или я не прав?
...
Рейтинг: 0 / 0
19.12.2006, 12:15
    #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
19.12.2006, 12:31
    #34210084
4321
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
st_sergЕсли уровень не Serializable, то разные операторы одной транзакции вполне могут увидеть разные данные, которая зафиксировала другая транзакция.
или я не прав?Вы правы. Особо, если учесть что единственным уровнем кроме Serializable в посгре является READ COMMITTED (умолчательный).

однако, поскольку мы (кажется) не можем (или я не прав?) порулить уровнем изоляции внутри процедуры (в данном случае - триггерной) - т.к. она заведомо выполняется внутри вызвавшей транзакции, то данное решение не устойчиво относительно выбора уровня изоляции (применив данное решение мы отказываем себе в удовольствии выполнять что-либо, затрагивающее данный триггер в режиме Serializable. Т.к. при конкуренции, приведшей к закольцовыванию цыкла, транзакция кажется повиснет в вечном лупе. Или таки вывалится с эксепшеном (что вряд ли - это ж не рекурсия, где ресурсы исчерпываются приводя к явной ошибке, а обычный цыкл) и ее придется рубить снаружи? Нет?
...
Рейтинг: 0 / 0
19.12.2006, 12:35
    #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
19.12.2006, 12:50
    #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
19.12.2006, 12:51
    #34210188
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
а версия пг?
...
Рейтинг: 0 / 0
19.12.2006, 12:57
    #34210211
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
ага, сори, мой косяк )
...
Рейтинг: 0 / 0
19.12.2006, 12:58
    #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
19.12.2006, 13:05
    #34210247
Драга
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
Код действительно взять из триггерной функции, забыл указать.

Вопрос, по крайней мере для меня, так и остался не проясненным. Этот код - руководство к действию и правильно писать именно так?
...
Рейтинг: 0 / 0
19.12.2006, 13:05
    #34210249
st_serg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
я работаю с oracle, а за пг просто наблюдаю, интересно... так что про сложные запросы ничего сказать не могу.
...
Рейтинг: 0 / 0
19.12.2006, 13:18
    #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
19.12.2006, 14:23
    #34210540
.gc
.gc
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
вопрос по самообразованию
Драга Этот код - руководство к действию и правильно писать именно так?
учитывая скрытые неприятные "сюрпризы" с этим кодом, которые проявляются при определенных условиях (хоть возможно и маловероятных), можно, например, добавить счетчик неуспешных проходов цикла и отваливаться с exception по превышению допустимого числа попыток :)

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


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