Recentemente, mudei de uma única instalação do MySQL para o MySQL Galera, rodando em 3 nós endereçados via HAProxy. Desde a troca, recebo aleatoriamente erros de "chave duplicada" relatados, o que teoricamente não deveria ser possível, pois verifico se o conjunto de dados já está disponível.
por exemplo:
MySQL Error executing stmt:
INSERT INTO user_ips
(user_id,ip)
VALUES
('444079','41.205.7.198, 176.9.19.101')
Error No: 1062
Error: Duplicate entry '444079-41.205.7.198, 1' for key 'user_id'
Meu código está assim:
function save_user_ip($user_id){
global $T62, $link;
$ip = $_SERVER['REMOTE_ADDR'];
// do we already know that user by this ip?
$stmt="
SELECT ID AS ip_id
FROM $T62
WHERE user_id = '$user_id' AND ip = '$ip'
";
$row = db_get_row2($stmt);
$ip_id = isset($row->ip_id) ? $row->ip_id : "";
if (!$ip_id){ // ip unknown for that user, save it
$stmt="
INSERT INTO $T62
(user_id,ip)
VALUES
('$user_id','$ip')
";
db_query($stmt);
$ip_id = db_insertid($link);
}
return $ip_id;
}
Executando isso em uma página de teste, funciona conforme o esperado. No servidor de produção sob carga, no entanto, nem sempre funciona. Pensei em INSERT IGNORE, mas prefiro não executar uma inserção em todas as ações, pois as gravações são mais lentas e também acionam um aviso.
A execução SHOW CREATE TABLE tablename
cria a seguinte saída: 1146 - A tabela 'tablename' não existe
Uma solução possível que parece funcionar pelo menos no cluster de desenvolvimento:
// save ip. Will ignore if already known ip
$stmt="
INSERT IGNORE INTO $T62
(user_id,ip)
VALUES
('$user_id','$ip')
";
#echo $stmt; exit;
db_query($stmt);
$ip_id = db_insertid($link);
// if ip already known, retrieve it
if (!$ip_id){
$stmt="
SELECT ID AS ip_id
FROM $T62
WHERE user_id = '$user_id' AND ip = '$ip'
";
$row = db_get_row2($stmt);
$ip_id = $row->ip_id;
}
return $ip_id;
Não tenho certeza de como isso melhora a situação no prod ou se torna as coisas ainda piores. Pode haver uma solução mais elegante.
Agradeço antecipadamente por qualquer ajuda sobre isso.
Erro do usuário.
Desde quando um
ip
parece41.205.7.198, 176.9.19.101
?444079-41.205.7.198, 1
implica que41.205.7.198, 1
foi o que foi usado como o arquivoip
. Esses são os primeiros 15 caracteres, então acho que você temVARCHAR(15)
. (Nota: é por isso que o primeiro comentário estava pedindoSHOW CREATE TABLE
.)Portanto, seu IP engraçado foi truncado, levando a uma CHAVE DUP causada pelo usuário.