powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / notify приходит через listen/notify, но данных "нет"
2 сообщений из 2, страница 1 из 1
notify приходит через listen/notify, но данных "нет"
    #39442125
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дев. сервер Windows 2008 R2 64bit, PostgreSQL 9.4.11 64bit (сборка от ентерпрайс диби).

ситуация следующая.

имеем процесс в котором один из потоков сидит и ждёт нотификации. получив нотификацию, он запускает поток который её обрабатывает, т.е. подключается к БД, селектит, апдейтит и т.д., закрывает соединение к БД и идёт спать, до следующего вызова.

имеем другой процесс, который делает вставку в таблицу, на которой висит, кроме всего прочего, триггер, который срабатывает после вставки и делает pg_notify('channel', 'payload');

после вставки, нотификация приходит, поток, которому она предназначена, стартует, делает SELECT из функции и, иногда не находит данные, которые присутствуют в таблице. если повторить SELECT, без какого либо другого INSERT'а и т.д. данные появляются. но проблема в том, что они иногда "отсутствуют" во время прихода нотификации о вставке. в функции для отладки добавлено RAISE LOG 'function_name(param_names) result %', FOUND; результаты совпадают с логом, т.е. когда апликация получает ответ что данных нету, в логе вижу запись function_name(param_names) result f.

таблица имеет индекс с WHERE condition, который предназначен для этой функции-запроса, который делается после полученной нотификации. хотя, в дев. сервере записей в этой таблице десятки, так что индекс по любому не используется.

может кто сталкивался с подобным явлением?

П.С. на боевом линукс пока не пробовал.


таблица:
Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
CREATE TABLE schema_name.t_task_table (
  id BIGSERIAL,
  object_id INTEGER NOT NULL,
  task_type_id INTEGER NOT NULL,
  period pg_catalog.tstzrange,
  done BOOLEAN,
  registered_at TIMESTAMP(0) WITH TIME ZONE DEFAULT now() NOT NULL,
  postponed_until TIMESTAMP(0) WITH TIME ZONE DEFAULT now() NOT NULL,
  retry_count INTEGER DEFAULT 0 NOT NULL,
  last_error TEXT,
  last_try TIMESTAMP(0) WITH TIME ZONE,
  CONSTRAINT t_task_table_pkey PRIMARY KEY(id),
  CONSTRAINT fk_t_task_table_objectid FOREIGN KEY (object_id)
    REFERENCES schema_name.t_object(id)
    MATCH FULL
    ON DELETE CASCADE
    ON UPDATE CASCADE
    NOT DEFERRABLE
) 
WITH (oids = false);

CREATE UNIQUE INDEX idx_t_task_table_task_todo ON schema_name.t_task_table
  USING btree (object_id, id)
  WHERE (done IS NULL);

CREATE TRIGGER tr_t_task_table_a_i
  AFTER INSERT 
  ON schema_name.t_task_table
  
FOR EACH ROW 
  EXECUTE PROCEDURE gpt_common.ftr_t_task_table_a_i();

CREATE TRIGGER tr_t_task_table_a_u
  AFTER UPDATE OF done 
  ON schema_name.t_task_table
  
FOR EACH ROW 
  WHEN (new.done IS NULL)
EXECUTE PROCEDURE gpt_common.ftr_t_task_table_a_u();

CREATE TRIGGER tr_t_task_table_b_u_r
  BEFORE UPDATE 
  ON schema_name.t_task_table
  
FOR EACH ROW 
  EXECUTE PROCEDURE gpt_common.ftr_t_task_table_b_u_r();



функция:
Код: sql
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.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
CREATE OR REPLACE FUNCTION gpt_system.f_function_name (
  p_schema text,
  p_objectid integer
)
RETURNS TABLE (
  task_id bigint,
  period_from timestamptz,
  period_to timestamptz
) AS
$body$
DECLARE
  l_qry TEXT;
BEGIN
  l_qry := concat($$
  SELECT
    t2.id,
    t2."period_from",
    t2."period_to"
  FROM (
    SELECT
      0 AS t,
      t.id,
      t."period_from",
      t."period_to"
    FROM (
      SELECT
        trd.id,
        lower(trd.period) AS "period_from",
        upper(trd.period) AS "period_to"
      FROM
        $$, concat($1, '.t_task_table')::regclass, $$ AS trd
      WHERE
        trd.object_id = $1 AND
        trd.done IS NULL AND
        trd.postponed_until < now()
      ORDER BY
        trd.postponed_until
      LIMIT 1
      ) AS t

    UNION ALL

    SELECT 
      1 AS t,
      0::BIGINT AS "task_id",
      now() - (
        (INTERVAL '1 day' * c.default_task_interval) +
        (INTERVAL '1 day' * GREATEST(c.default_task_interval / 4, 1))
      ) AS "period_from",
      now() AS "period_to"
    FROM
      gpt_system.t_customer AS c  
    WHERE
      c.schema_name = $2 AND
      NOT EXISTS (
        SELECT
          1
        FROM
          $$, concat($1, '.t_object')::regclass, $$ AS oti
        WHERE
          oti.object_id = $1 AND
          oti.need_read_now = FALSE AND
          oti.last_downloaded >= (
            now() - (INTERVAL '1 day' * c.default_task_interval)
          )
        )
    ) AS t2
  ORDER BY
    t2.t
  LIMIT 1
  $$);
  
  RETURN QUERY
  EXECUTE l_qry
  USING $2, $1;
  
  RAISE LOG 'f_function_name(x,y) %', FOUND;
END;
$body$
LANGUAGE 'plpgsql'
STABLE
RETURNS NULL ON NULL INPUT
SECURITY INVOKER
COST 100 ROWS 1;



insert:
Код: sql
1.
2.
INSERT INTO schema_name.t_task_table (object_id, task_type_id, period) 
VALUES (13, 57, '["2017-01-31 02:00:00+02","2017-02-15 02:00:00+02"]'::tstzrange);

...
Рейтинг: 0 / 0
notify приходит через listen/notify, но данных "нет"
    #39442128
Lonepsycho
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lonepsycho,

пока писал, похоже и нашёл:

Код: sql
1.
trd.postponed_until < now()



буду тестировать...
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / notify приходит через listen/notify, но данных "нет"
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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