skip to Main Content

Here is the scenario. This table Orders has an auto_increment column called orders_id. The table uses InnoDB storage engine. (This is not about inserting new records in the Orders table, its about how to avoid sending duplicate IDs to the processor)

orders_id       cust_id       name       address 
100              55           abc        123 street    
101              12           def        456 street   

For the next order, I calculate the next available Orders_id like so

$new_order_id_query = "SHOW TABLE STATUS LIKE ORDERS";
$result = tep_db_query($new_order_id_query);
$row = tep_db_fetch_array($result);
$new_order_id = $row['Auto_increment'];

Then I collect other information like name, address, items_ordered… and send it to the payment processor like this

102              44           xyz         44 Street

The problem is only sometimes when there are two or more orders at exactly the same time, I end up sending two orders with the same orders_id to the payment processor.

The question is how can I make sure that I am not sending a duplicate Orders_id to the Payment Processor?

I have been suggested to use last_insert_id() which may be right or wrong but I dont know how I can implement it.

I read about Locking Tables – Is that a good idea for a Transaction Environment and InnoDB? If so how can I implement it?

4

Answers


  1. auto_increment columns normally do not require manipulation in your code. When you insert new record column defined with auto_increment is automatically incremented.

    last_insert_id is used to obtain the value that was assigned to your automatically incremented field within your connection context.

    I would not recommend locking table in your case, because you didn’t provide any grounds to do so in your problem statement.

    Login or Signup to reply.
  2. As explained in my answer to your last question:

    1. Collect the name, address, items_ordered, etc.

    2. Insert relevant detail into the orders table, omitting to provide an id (MySQL will automatically generate one for you, guaranteeing its uniqueness through the use of locks).

    3. Obtain the generated id from MySQL by asking it for last_insert_id (the actual function call will depend on your driver).

    4. Send to your payment processor.

    Login or Signup to reply.
  3. You don’t need to calculate what the next order ID will be. Auto increment automatically makes the next ID for you when you insert a row into that table. That is the whole point of it.

    All you need to do is run an insert that puts in all the other information into the table, without specifying a value for the auto_increment field.

    "INSERT INTO Orders (cust_id, name, address) VALUES (55, 'me', 'My House')"
    

    If you want to find out what the order ID was of the row you just inserted, simply call last_insert_id() on the query result. I don’t know what tep_db is, as it’s not something I’ve used but I think you want the function tep_db_insert_id().

    Login or Signup to reply.
  4. I am calculating the ID because I need to send it to the Payment Processor before the actual insertion takes place.

    All techniques you’ve mentioned require that you open a database connection and keep it open between different HTTP requests (while you prevent other scripts instances from using it) so can benefit from a single database session. There’s no reliable way to do so.

    I haven’t worked with osCommerce for ages (I’m surprised it still exists 🙂 but you basically have two possibilities:

    • Insert a real order the usual way, but tag it as pending.
    • Insert a pre-order in another table (possibly designed by you).

    I honestly think you need to save the order before redirecting to payment gateways. If you trust session data you’ll lose orders sooner or later; and you’ll lose payed orders, which is worse.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search