Hi,
folgendes Skript wird von mindestens zwei PHP-Prozessen (A, B) parallel ausgefuehrt.
[...]
$conn->begin_transaction();
for($i = 0; $i < 5; $i++)
{
$max_id = $conn->db_get_value('select max(primary_id) + 1 AS max_id from tabelle');
$conn->db_access('insert into tabelle (primary_id) VALUES ('.$max_id.')');
}
$conn->end_transaction();
[...]
Es startet jeweils eine Transaktion, ermittelt die aktuell hoechste ID der Tabelle und addiert 1, und schreibt einen neuen Satz mit dieser neuen hoechten ID, und wiederholt das (hier testweise insgesamt 5 mal in der for-Schleife), und beendet die Transaktion.
Dadurch, dass dieses Skript parallel von mehrerer Prozessen ausgefuehrt wird, kann es sein, dass Prozess A beim 1. Durchlauf der Schleife einen neuen Datensatz mit ID Y anlegen will, und dadurch, das Prozess B parallel laeuft, auch dieser einen Datensatz mit ID Y anlegen will, da er die max-id ermittelt hat, bevor (!) Prozess A das INSERT ausgefuehrt hat.
Ich habe das einige Male getestet, in der Regel funktioniert es, da, sobald ein INSERT begonnen wurde, der andere Prozess, der ja auch in einer Transaktion liegt wartet, bis die andere INSERT-Batch-Transaktion fertig ist.
Allerdings hat es auch ein paar mal aus oben genannten Grund gekracht, da die SELECTS (fast) gleichzeitig fertig waren und vorallem BEVOR einer der INSERTS abgesetzt wurde.
Wie kann man das 100% umgehen?
Trigger, Auto-ID, Locks?
Danke & Servus