[Pgpool-general] node degeneration on INSERT

Karsten Düsterloh pgpool-general-ml at tal.de
Thu Jun 30 09:12:55 UTC 2011


Hi!

We're still experiencing node degeneration with certain INSERTs,
but now (finally!) I have a testcase!

We're running pgpool-II 2.3.3 with two Postgresql 8.3.11 nodes.
Certain tables sport an 'id' field, tied to a SEQUENCE as the default
value. INSERT queries for these tables come in two flavours:
- read next id from SEQUENCE and INSERT with that id explicitly set
- INSERT without setting the id, let Postgresql set it automatically

This will occasionally fail with
> ERROR:  kind mismatch among backends. Possible last query was: 
> "INSERT INTO locktest(id, ts) VALUES(127, Now());" kind details are:
> 0[C] 1[E: duplicate key value violates unique constraint
> "locktest_pkey"]
> HINT:  check data consistency among db nodes

We didn't test with pgpool-II 3. It'd be good to know if that'd be fixed
there.



Testcase:

1. Setup pgpool with two client nodes:
 replication_mode = true
 load_balance_mode = true
 replication_stop_on_mismatch = true
 failover_if_affected_tuples_mismatch = true

2. Create the following table:
 create table locktest(id SERIAL primary key, ts timestamptz);

3. Create three small shell scripts in one directory:

test1_ex.sh:
============
#!/bin/bash
PSQL="/path/to/your/psql -your -access -options -Aqt -c"
while true; do
  TID=$($PSQL "SELECT nextval('locktest_id_seq');")
  $PSQL "INSERT INTO locktest(id, ts) VALUES($TID, Now());"
done

test1_im.sh:
============
#!/bin/bash
PSQL="/path/to/your/psql -your -access -options -Aqt -c"
while true; do
  $PSQL "INSERT INTO locktest(ts) VALUES(Now());"
done

test1.sh:
=========
#!/bin/bash
./test1_ex.sh &
./test1_im.sh &

4. Run test1.sh and wait for node degeneration.

Step 4 took less then 10 minutes for me until degeneration.



Analysis:

When inserting new rows, the *table* locktest will be locked so that
both INSERTs can't disturb each other. But the dependend *sequence* will
not be locked, hence the explicit call to nextval may happen while the
table is already locked but the implicit nextval didn't happen yet:

Example: (LOCKs are generated by pgpool)

node 0:
[im] LOCK
[im] INSERT INTO locktest(ts) VALUES(Now());
[ex] SELECT nextval('locktest_id_seq');
[ex] LOCK
[ex] INSERT INTO locktest(id, ts) VALUES(xxx, Now());

node 1:
[im] LOCK
[ex] SELECT nextval('locktest_id_seq');
[im] INSERT INTO locktest(ts) VALUES(Now());
[ex] LOCK
[ex] INSERT INTO locktest(id, ts) VALUES(xxx, Now());

Maybe pgpool should/could LOCK implicitly used sequences as well?



Karsten


More information about the Pgpool-general mailing list