简体   繁体   中英

SELECT LAST_INSERT_ID() intermittently returns 0

I have searched many similar questions though i can't find any that intermittently returns 0

**** EDIT *****

I have since tried testing with a new table with only two columns, reduces the issue to around 1 in 50 times returning zero.

I have also just now been able to test on a paid hosting server and i could not replicate my issue

I assume the issue my be specific to that web host.

Issue:

When trying to retrieve the last inserted ID on a per connection basis, roughly 4 times out of ten i get a 0 returned to me.

Localhost, everything works fine without issue. The issue only arises when my website is hosted on a server.

SELECT LAST_INSERT_ID() intermittently returns 0

$PDOconnection->lastInsertId(); Always returns correct ID

I need to reliably get last inserted ID on a per connection basis as it's essential to the checkout process of my website when creating a purchase order in the database.

Notes:

  • The ID is auto-incremented
  • The sql insert always works fine and the database shows a new entry.
  • Switching PHP version does not resolve the issue
  • Web host i'm using is a free hosting service i'm using for live testing purposes
  • Page load time is always similar (500 - 750ms for the code below)

I stripped the entire code down(as below) to test in simplicity. Issue still remains

I can't seem to workout where my issue lies.

include_once "php/config.php";

$cookie_id = 0;

// Time of checkout
$time = gmdate("d/m/Y h:i:s");

// Create new purchase order
$sql_insert = "INSERT INTO user_purchases (cart_id, timestamp) VALUES (:cookie_id, :time)";

$stmt_insert = $PDOconnection->prepare($sql_insert);
$stmt_insert->bindParam(':cookie_id', $cookie_id, PDO::PARAM_STR);
$stmt_insert->bindParam(':time', $time, PDO::PARAM_STR);
$stmt_insert->execute();

$checkout_id_0 = $PDOconnection->lastInsertId();

// Get the primary key id of the last inserted item on per-connection basis
$sql_last_id = "SELECT LAST_INSERT_ID()";
$stmt_last_id = $PDOconnection->prepare($sql_last_id);
$stmt_last_id->execute();
$r_last_id = $stmt_last_id->fetch(PDO::FETCH_ASSOC);

$checkout_id_1 = $r_last_id['LAST_INSERT_ID()'];

echo $checkout_id_0 . " " . $checkout_id_1;  // I echoed out to observe results

Real example of results for 10 queries in a row (simply by just refreshing the page). I echoed the results out side by side.

checkout_id_0      $checkout_id_1  <---SELECT LAST_INSERT_ID()

      16                16
      17                17
      18                0        // Returned 0
      19                19
      20                0        // Returned 0
      21                0        // Returned 0
      22                22
      23                23
      24                23       // Returned previous ID (happens 1/30 tries)
      25                25

Connection config:

$PDOconnection = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8", $sql_username, $sql_password);

// Set PDO error mode to exception
$PDOconnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// Set PDO Attribute to force native prepared statements
$PDOconnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Have you tried activating persistent connections? See Connections and Connection management and Persistent Database Connections . Maybe that remote server has too short MySQL settings - wait_timeout and interactive_timeout ...

Persistent connections are not closed at the end of the script, but are cached and re-used when another script requests a connection using the same credentials. The persistent connection cache allows you to avoid the overhead of establishing a new connection every time a script needs to talk to a database, resulting in a faster web application.

Also note:

If you wish to use persistent connections, you must set PDO::ATTR_PERSISTENT in the array of driver options passed to the PDO constructor. If setting this attribute with PDO::setAttribute() after instantiation of the object, the driver will not use persistent connections.

So:

$PDOconnection = new PDO(
    "mysql:host=$servername;dbname=$dbname;charset=utf8"
    , $sql_username
    , $sql_password
    , array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_EMULATE_PREPARES => false,
        PDO::ATTR_PERSISTENT => true,
    )
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM