У меня странная ситуация.
Предположим, у меня есть очень простая функция в php (я использовал Yii, но проблема общая), которая вызывается внутри оператора транзакции:
public function checkAndInsert($someKey)
{
$data = MyModel::model()->find(array('someKey'=>$someKey)); // search a record in the DB.If it does not exist, insert
if ( $data == null)
{
$data->someCol = 'newOne';
$data->save();
}
else
{
$data->someCol = 'test';
$data->save();
}
}
...
// $db is the instance variable used for operation on the DB
$db->transaction();
$this->checkAdnInsert();
$db->commit();
Тем не менее, если я запусту скрипт, содержащий эту функцию, запустив много процессов, у меня будут двойные значения в БД. Например, если у меня есть $ someKey = ‘pippo’, и я запускаю сценарий, запустив 2 процесса, у меня будет две (или более) записи со столбцом «someCol» = «newOne». Это происходит случайно, не всегда.
Код неправильный? Должен ли я поставить некоторые ограничения в БД в виде ключей?
Я тоже читаю эта почта о добавлении уникальных индексов в TokuDB, который говорит, что UNIQUE KEY «убивает» производительность записи …
У вас неправильный подход. Это неправильно, потому что вы делегируете полномочия по проверке целостности / уникальности PHP, но за это отвечает база данных.
Другими словами, вам не нужно проверять, существует ли что-то, а затем вставлять. Это плохо, потому что между PHP и MySQL всегда присутствует небольшой пинг, и, как вы уже видели, вы можете получить ложные результаты для ваших проверок.
Если вам нужны уникальные значения для определенного столбца или комбинации столбцов, вы добавляете UNIQUE
ограничение. После этого вы просто вставляете. Если запись существует, вставка не удалась, и вы можете справиться с ней через Exception
, Мало того, что это быстрее, это также легче для вас, потому что ваш код может стать однострочным, который намного легче поддерживать или понимать.
Других решений пока нет …