Есть у нас сайт, который работает с FB:
Server Version: LI-V1.5.2.4731 Firebird 1.5
Server Implementation: Firebird/linux Intel
Скрипты на php. С них идут обновления (счетчики увеличиваются) и часто имеется следующее:
deadlock update conflicts with concurrent update
Я это дело как увидел, очень удивился, потому что вроде не должно быть этого (http://ibase.ru/devinfo/norecver.htm).
Транзакция на обновление пускается с параметрами:
IBASE_WRITE | IBASE_COMMITTED | IBASE_WAIT |
IBASE_REC_NO_VERSION
Сформировал минимальный тест (база в 1 табличку, скрипт в 100 строчек), начал гонять его с помощью апачевской утилиты нагрузочного тестирования (ab). И получил, что ИНОГДА действительно эта ошибка выскакивает. А иногда - нет. В общем, очень неустойчивое поведение, но все-таки воспроизводится.
Табличка такая:
Код: Выделить всё
CREATE TABLE TEST (
ID INTEGER NOT NULL,
CNT INTEGER DEFAULT 0 NOT NULL
);
Код: Выделить всё
<HTML>
<?
function WriteLog($msg)
{
$LogFileName = '/tmp/test.log';
$msg = date('d-m-Y H:i:s') . " > " . $msg . "\r\n";
$f = fopen($LogFileName, "a+");
fwrite($f, $msg);
fclose($f);
}
function DieError($msg)
{
$msg .= ": " . ibase_errmsg();
echo nl2br($msg);
WriteLog($msg);
die;
}
$charset = "win1251";
$buffers = 0;
$dialect = 3;
$role = "";
$dbname = "localhost:/db/test.gdb";
$user = "sysdba";
$password = "********";
$WriteTransParams = IBASE_WRITE | IBASE_COMMITTED | IBASE_WAIT | IBASE_NO_REC_VERSION;
// Соединяемся
$db = @ibase_connect($dbname, $user, $password, $charset, $buffers, $dialect, $role) or DieError("Connection failed");
echo "\$db = $db<br>\r\n";
// Стартуем пишущую транзакцию
$tran = @ibase_trans($WriteTransParams) or DieError("Transaction start failed") ;
echo "\$tran = $tran<br>\r\n";
// Выполняем запрос
$q = @ibase_query("UPDATE TEST SET CNT = CNT + 1 WHERE ID = ?", 1) or DieError("Query execution failed");
echo "\$q = $q<br>\r\n";
// Немножко ждем (мкс)
usleep((int)(0.1 * 1000000));
// Фиксируем транзакцию
@ibase_commit($tran) or DieError("Commit failed");
echo "Committed.<br>\r\n";
?>
</HTML>
ab -n 3000 -c 64 "http://testserver/test.php"
И смотрим лог, который пишет скрипт.
Иногда видим там пачку deadlock update conflicts with concurrent update.
Что делать???
Ну, попытаться обойти это мы можем, устроить очередь на обновление и все такое - это понятно.
Но вообще - непорядок...