문제

I recently switched from a single MySQL installation to MySQL Galera, running on 3 nodes addressed via HAProxy. Ever since switching I do get randomly "duplicate key" errors reported which theoretically should not be possible as I do check if the dataset is already available.

e.g.:

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'

My code looks like this:

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;
}

Running this on a test page it works as intended. On the production server under load it however does not always work. I thought about INSERT IGNORE but would rather not run an insert on all actions as writes are slower and it also triggers a warning.

Running SHOW CREATE TABLE tablename creates following output: 1146 - Table 'tablename' doesn't exist

One possible solution that seems to work at least on development cluster:

// 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;

Not sure how this improves the situation on prod or if it makes things even worse. There might be a more elegant solution.

Thank you in advance for any help on this.

도움이 되었습니까?

해결책

User error.

Since when does an ip look like 41.205.7.198, 176.9.19.101?

444079-41.205.7.198, 1 implies that 41.205.7.198, 1 was what was used as the ip. That's the first 15 characters, so I guess you have VARCHAR(15). (Note: this is why the first comment was asking for SHOW CREATE TABLE.)

So, your funny IP got truncated, leading to a user-caused DUP KEY.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 dba.stackexchange
scroll top