BUG or strange behaviour of update on primary key

From: desmodemone <desmodemone(at)gmail(dot)com>
To: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Cc: l(dot)denardo(at)miriade(dot)it, f(dot)dalmaso(at)miriade(dot)it
Subject: BUG or strange behaviour of update on primary key
Date: 2011-10-17 22:09:35
Message-ID: CAEs9oFmNtMru-tO9rZQUYpCNDqVHryVOZtQr8X9gJMO8cMo62g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hello there,
two guys of our developer team ( Lorenzo and Federico )
have seen a strange behaviour (in 8.4 and 9.1.1 ) on update, and I think is
a bug or something really strange or I not understand correctly this
behavior .

I explain now ( begin transaction or auto commit is the same):

create table testup ( a int ) ;

alter table testup add primary key (a ) ;

insert into testup values (1);

insert into testup values (2);

update testup set a=a+1 ;
ERROR: duplicate key value violates unique constraint "testup_pkey"
DETTAGLI: Key (a)=(2) already exists.

by the way :

test=# update testup set a=a-1 ;
UPDATE 2
SUCCESFUL

-- REVERSE ORDER --

Now create the same table with rows in reverse physical order:

create table testup2 ( a int ) ;

alter table testup2 add primary key (a ) ;

insert into testup2 values (2) ;

insert into testup2 values (1);

update testup2 set a=a+1 ;
UPDATE 2
SUCCESFUL

by the way :

test=# update testup2 set a=a-1 ;
ERROR: duplicate key value violates unique constraint "testup2_pkey"
DETTAGLI: Key (a)=(1) already exists.

I have tested in Oracle 11gR1 and 11gR2 without the same behaviour :

Oracle :

SQL> create table a ( b number ) ;

Tabella creata.

SQL> alter table a add primary key (b) ;

Tabella modificata.

SQL> insert into a values (1 ) ;

Creata 1 riga.

SQL> insert into a values (2) ;

Creata 1 riga.

SQL> commit ;

Commit completato.

SQL> update a set b=b+1 ;

Aggiornate 2 righe.

SQL> commit ;

Commit completato.

SQL> update a set b=b-1;

Aggiornate 2 righe.

SQL> commit;

Commit completato.

In MySQL 5.1.58 with InnoDB the behaviour is more strange (always for +1
and indipendent from the reverse order O_o) :

mysql> create table testup ( a int ) engine innodb ;
Query OK, 0 rows affected (0.21 sec)

mysql> alter table testup add primary key (a) ;
Query OK, 0 rows affected (0.34 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> insert into testup values (1) ;
Query OK, 1 row affected (0.12 sec)

mysql> insert into testup values (2) ;
Query OK, 1 row affected (0.15 sec)

mysql> commit ;
Query OK, 0 rows affected (0.00 sec)

mysql> update testup set a=a+1 ;
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY' (-- like
postgres!)
mysql> update testup set a=a-1 ;
Query OK, 2 rows affected (0.16 sec)
Rows matched: 2 Changed: 2 Warnings: 0

mysql> commit ;
Query OK, 0 rows affected (0.00 sec)

mysql> update testup set a=a+1 ;
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> select * from testup ;
+---+
| a |
+---+
| 0 |
| 1 |
+---+
2 rows in set (0.00 sec)

-- REVERSE ORDER --

mysql> truncate table testup ;
Query OK, 0 rows affected (0.11 sec)

mysql> insert into testup values (2) ;
Query OK, 1 row affected (0.12 sec)

mysql> insert into testup values (1) ;
Query OK, 1 row affected (0.17 sec)

mysql> update testup set a=a+1 ; (-- O_O is tottaly different from
postgres!)
ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
mysql> update testup set a=a-1 ;
Query OK, 2 rows affected (0.16 sec)
Rows matched: 2 Changed: 2 Warnings: 0

In MySql with Myisam is tottaly different and similar to Oracle :

mysql> create table testup_myisam ( a int ) engine myisam ;
Query OK, 0 rows affected (0.17 sec)

mysql> insert into testup_myisam values (2) ;
Query OK, 1 row affected (0.00 sec)

mysql> insert into testup_myisam values (1) ;
Query OK, 1 row affected (0.00 sec)

mysql> update testup_myisam set a=a+1 ;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0

mysql> update testup_myisam set a=a-1 ;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0

-- REVERSE ORDER --

mysql> truncate table testup_myisam ;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into testup_myisam values (1) ;
Query OK, 1 row affected (0.00 sec)

mysql> insert into testup_myisam values (2) ;
Query OK, 1 row affected (0.00 sec)

mysql> update testup_myisam set a=a+1 ;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0

mysql> update testup_myisam set a=a-1 ;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0

The problem for us is when we develop or migrate applications between
different databases.
By the way I think is not right that an update on the same set of rows will
be successful or failed if the rows are ordered or not, no?
I think it is something in correlation with visibility of rows in MVCC
(update=>insert + delete tuple).

What do you think about?

See you soon

Regards, Mat

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2011-10-17 22:59:16 Re: BUG or strange behaviour of update on primary key
Previous Message Chris Redekop 2011-10-17 21:30:49 Re: Hot Backup with rsync fails at pg_clog if under load