Bug #29212 LAST_INSERT_ID doesn't work for innodb on "on duplicate key update"
Submitted: 19 Jun 2007 13:42 Modified: 20 Jun 2007 5:00
Reporter: Nikolay Pelov Email Updates:
Status: Duplicate Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:5.0.37 OS:Linux
Assigned to: CPU Architecture:Any

[19 Jun 2007 13:42] Nikolay Pelov
Description:
on duplicate key doesn't update LAST_INSERT_ID for INNODB storage engine. 

This is tested in mysql 5.0.37 (and some versions below)

How to repeat:
CREATE TABLE `words` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, 
  `word` VARCHAR(32) NOT NULL, 
  `cnt` INT UNSIGNED NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `word` (`word`)
)TYPE = innodb;

mysql> INSERT INTO words (word,cnt) VALUES ('test',1) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), cnt=cnt+1;
Query OK, 1 row affected (0.01 sec)

mysql> SELECT LAST_INSERT_ID();                                                 +------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO words (word,cnt) VALUES ('test',1) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), cnt=cnt+1;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT LAST_INSERT_ID();                                                 +------------------+
| LAST_INSERT_ID() |
+------------------+
|                0 |
+------------------+
1 row in set (0.00 sec)

mysql> SELECT * from words;
+----+------+-----+
| id | word | cnt |
+----+------+-----+
|  1 | test |   2 |
+----+------+-----+
1 row in set (0.00 sec)

Suggested fix:
An workaround is:
1. use transactions:
BEGIN;
select id from words where word='test' FOR UPDATE; #set lock
INSERT INTO words (word,cnt) VALUES ('test',1) ON DUPLICATE KEY UPDATE cnt=cnt+1;
select id from words where word='test';#get id
COMMIT;#commit and release lock
2. use myisam table type
[20 Jun 2007 5:00] Valeriy Kravchuk
This is a duplicate of bug #27033. Already fixed since 5.0.40.