mysql_insert_id и last_insert_id неправильное поведение

у меня есть эта таблица

 CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  ;

a_b — уникальный ключ.

И у меня есть такой php-код

 $db = DBFactory::getInstance();
 $db->selectDB('test');
 $db->query("insert into t5 (a, b) values(1, 1) on duplicate key update a=1, b=1");
 var_dump(mysql_insert_id());

 $cur = $db->query("select last_insert_id()");
 var_dump(mysql_fetch_assoc($cur));

Запустив этот код дважды, на моем компьютере результат будет 1-й.

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

2nd

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

Вы можете видеть, что оба раза mysql_insert_id() возвращает одно и то же значение «1», это нормально для меня, потому что я хочу знать реальный идентификатор после вставки, а не следующее значение auto_increment.

Но когда я дважды запускал этот код в другой среде: 1-й

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

2nd

int(2)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

Как видите, результат второго раза mysql_insert_id() возвращает то же значение, что и last_insert_id().

Этот результат ужасен, но я не знаю, почему. Мои коды отлично работают в обеих средах около 3 месяцев, и до сегодняшнего дня этого не случалось. может кто-нибудь объяснить? Я обновил версию PHP второй среды до 5.3.8 около 30 дней назад, и никаких других изменений. Это ошибка?

обновить

Я переключаюсь на третий сервер mysql (5.1.38-log), вторая вставка возвращает int (0) array (1) { ["last_insert_id()"] => string (1) "0" }

Итак, я понял, что проблема может быть в версии mysql.

Наконец, я изменил определение таблицы на это

DROP TABLE IF EXISTS `t5`;
CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `t` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Также отредактируйте мой сценарий

$db = DBFactory::getInstance();
$db->selectDB('test');
$db->query("insert into t5 (a, b, t) values(1, 1, ".time().") on duplicate key update a=1, b=1, t=".time());
//$db->query("insert ignore into t5 (a, b) values(1, 1)");
var_dump(mysql_insert_id());

$cur = $db->query("select last_insert_id()");
var_dump(mysql_fetch_assoc($cur));

Разные серверы mysql возвращают один и тот же mysql_insert_id, но разные last_insert_id()

5.0.24a-сообщество-nt

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

5.0.51a-журнал

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

Журнал 5.1.38

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "0"
}

Есть ли какие-либо системные переменные, управляющие этим поведением? Если кто-то знает, это будет приветствовать. Если нет решения, единственное, что я могу сделать, это заставить вставку, подобную этой, обновить какое-то поле с другим значением...


person Matt.Z    schedule 09.12.2011    source источник
comment
Вы используете одну и ту же схему в одном и том же экземпляре базы данных? Возможно ли, что во втором случае УНИКАЛЬНОГО ключа по какой-то причине нет?   -  person liquorvicar    schedule 09.12.2011
comment
Указывают ли эти экземпляры на одну и ту же базу данных MySQL или на разные?   -  person Simon    schedule 09.12.2011
comment
В обеих базах данных после двойной вставки в таблице есть только одна строка, это несомненно.   -  person Matt.Z    schedule 09.12.2011
comment
Указывают ли эти экземпляры на одну и ту же базу данных MySQL или на разные? разные базы данных, мой локальный mysql (на ПК) — 5.0.24a-community-nt, а другой — 5.0.51a-log (на Linux)   -  person Matt.Z    schedule 09.12.2011
comment
Спасибо, Саймон, напоминание, я использую php-скрипт своего ПК для подключения mysql к linux и запускаю код, но все еще получаю mysql_insert_id () = 2, так что это ошибка mysql? Я перезапустил службу mysql, но она все равно дает мне неправильный результат.   -  person Matt.Z    schedule 09.12.2011
comment
last_insert_id не является потокобезопасным. Вы делаете что-то еще с тем же соединением?   -  person idstam    schedule 09.12.2011


Ответы (1)


Я думаю, вы пытаетесь использовать last_insert_id() не так, как должно быть - в этом случае вы ничего не вставляете, поэтому вам также не следует доверять возвращаемому значению. Из документов MySQL:

Если таблица содержит столбец AUTO_INCREMENT, а INSERT ... UPDATE вставляет строку, функция LAST_INSERT_ID() возвращает значение AUTO_INCREMENT. Если оператор вместо этого обновляет строку, LAST_INSERT_ID() не имеет смысла.

Однако похоже, что для этого (тот же документ) есть обходной путь - ручная установка last_insert_id:

Однако вы можете обойти это, используя LAST_INSERT_ID (expr). Предположим, что id — это столбец AUTO_INCREMENT. Чтобы сделать LAST_INSERT_ID() значимым для обновлений, вставьте строки следующим образом:

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

person Aurimas    schedule 09.12.2011