This happens due to the nature of ajax calls – they are asynchronous. When you have a lengthy function (or heavy plugins and slow site loading), several ajax calls are running at the same time, and nobody can predict, which one will get access to db data faster.
Usage of own tables is not a solution in this situation.
The easiest way to solve the problem is to block further adding of a product by Javascript until current ajax is finished.
So, sequence of actions in js should be:
-
by the click on the add to cart button set flag blocking other clicks
-
run ajax
-
in .complete function delete the flag so allowing further add to cart clicks