> On Feb 13, 2017, at 10:28 AM, Adrian Klaver <[email protected]> wrote:
>
> On 02/10/2017 02:54 PM, François Beaulieu wrote:
>>
>> Hi all,
>>
>> I’m trying to feed a worker process on another server using pg_notify in a
>> trigger. I’m running pgsql 9.4 and hitting some behaviour that I’m hoping is
>> just a bug that can be solved with an upgrade, but I’m not finding any
>> references to it being a known bug and the uptime on my database server is
>> critical so I can’t upgrade on a whim. Basically, the trigger runs on every
>> row insert and notifies me with a few fields from the row. This works
>> perfectly most of the time, but every few hundred rows, the notify will
>> return null values. Here are the details:
>>
>> My database uses time-based partitioning (and subpartitioning) with
>> pg_partman. This is done with a before insert trigger on the main parent
>> table. pg_partman creates subtables dynamically, so I can’t easily run my
>> trigger on each child table. I also can’t run it after insert on my parent
>> table because the row never makes it there. Thus, I ave elected to run my
>> trigger before insert on the parent table, and have named it so that it is
>> alphabetically first and will run before the partitioning trigger. Works
>> perfectly most of the time. Here are the trigger and associated plpgsql
>> function:
>>
>> —CODE---
>> CREATE OR REPLACE FUNCTION notify_trigger() RETURNS trigger AS $$
>> DECLARE
>> BEGIN
>> PERFORM pg_notify('watchers', TG_TABLE_NAME || ',' || NEW._id || ',' ||
>> NEW.userfield);
>> RETURN new;
>> END;
>> $$ LANGUAGE plpgsql;
>>
>> CREATE TRIGGER aaa_notify BEFORE INSERT ON aaa FOR EACH ROW execute
>> procedure notify_trigger();
>> —/CODE—
>>
>> On my listener, every once in a while, this returns rows such as this:
>>
>> AAA,17947227,XXX
>> AAA, ,
>> AAA,17947229,ZZZ
>>
>> Notice the second line, which appears to have even the autoincrement ‘_id'
>> empty. It would seem to match _id = 17947228 and that row does exist in the
>> table and has data populated for all fields.
>>
>> Has anyone ever seen anything like this?
>
> Can't say I have. I think this is going to need more information:
>
> --
> Adrian Klaver
> [email protected]
> 1) What is the schema for the parent table?
Table "public.cdr"
Column | Type | Modifiers
| Storage | Stats target | Descripti
on
-------------+-----------------------------+---------------------------------------------------+----------+--------------+----------
---
_id | bigint | not null default
nextval('cdr__id_seq'::regclass) | plain | |
calldate | timestamp without time zone | not null
| plain | |
callanswer | timestamp without time zone |
| plain | |
callend | timestamp without time zone | not null
| plain | |
clid | character varying(80) |
| extended | |
dnid | character varying(80) |
| extended | |
src | character varying(80) |
| extended | |
dst | character varying(80) | not null
| extended | |
dcontext | character varying(80) | not null
| extended | |
channel | character varying(80) | not null
| extended | |
dstchannel | character varying(80) |
| extended | |
lastapp | character varying(80) |
| extended | |
lastdata | character varying(80) |
| extended | |
duration | integer | not null
| plain | |
billsec | integer | not null
| plain | |
disposition | character varying(45) | not null
| extended | |
amaflags | integer | not null
| plain | |
accountcode | character varying(20) |
| extended | |
uniqueid | character varying(150) | not null
| extended | |
userfield | character varying(255) |
| extended | |
Indexes:
"cdr_pkey" PRIMARY KEY, btree (_id, calldate)
"cdr__id_idx" btree (_id)
"cdr_accountcode_idx" btree (accountcode)
"cdr_amaflags_idx" btree (amaflags)
"cdr_calldate_idx" btree (calldate)
"cdr_clid_idx" btree (clid)
"cdr_disposition_idx" btree (disposition)
"cdr_dnid_idx" btree (dnid)
"cdr_dst_idx" btree (dst)
"cdr_src_idx" btree (src)
"cdr_uniqueid_idx" btree (uniqueid)
"cdr_userfield_idx" btree (userfield)
Triggers:
cdr_notify BEFORE INSERT ON cdr FOR EACH ROW EXECUTE PROCEDURE
notify_trigger()
cdr_part_trig BEFORE INSERT ON cdr FOR EACH ROW EXECUTE PROCEDURE
cdr_part_trig_func()
Child tables: cdr_p2016w06,
cdr_p2016w07,
cdr_p2016w08,
cdr_p2016w09,
cdr_p2016w10,
etc…
> 2) What is the pg_partman trigger function definition, as well the CREATE
> TRIGGER definition that calls the function?
cdr_part_trig BEFORE INSERT ON cdr FOR EACH ROW EXECUTE PROCEDURE
cdr_part_trig_func()
public | cdr_part_trig_func | trigger |
| trigger | invoker | volatile | postgres |
plpgsql |
+|
| | |
| | | | |
| BEGIN
+|
| | |
| | | | |
| IF TG_OP = 'INSERT' THEN
+|
| | |
| | | | |
| IF NEW.calldate >= '2017-02-13 00:00:00+00' AND
NEW.calldate < '2017-02-20 00:00:00+00' THEN +|
| | |
| | | | |
| INSERT INTO public.cdr_p2017w07 VALUES (NEW.*);
+|
| | |
| |
| ELSIF NEW.calldate >= '2017-02-06 00:00:00+00' AND
NEW.calldate < '2017-02-13 00:00:00+00' THEN +|
| | |
| | | | |
| INSERT INTO public.cdr_p2017w06 VALUES (NEW.*);
+|
[…]
| | |
| | | | |
| ELSE
+|
| | |
| | | | |
| RETURN NEW;
+|
| | |
| | | | |
| END IF;
+|
| | |
| | | | |
| END IF;
+|
| | |
| | | | |
| RETURN NULL;
+|
| | |
| | | | |
| END
|
|
> 3) Are the first row and the second row in the same partition?
Doubtful, the problem occurs several times a day and we only have one partition
a day. Let me check with the above example. What would be the best way to
determine which child a row is in, and the relative position in the child table?
Also; my worker in written in perl and uses DBD::Pg. I haven’t been able to
100% eliminate the module itself as the cause of the bug. Any suggestions on
how I might go about doing that efficiently?
Thanks,
-=François Beaulieu
SBK Telecom
--
Sent via pgsql-general mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general