2016-06-20 12 views
1

Ich habe folgendes ModellUpdates in mysql Transaktion - Isolation

Inventory [product_name, quantity, reserved_quantity] 

mit Daten

[Shirt, 1, 0] 
[Shorts, 10, 0] 

Was passiert, wenn folgender Code geschieht in mehreren Threads gleichzeitig ausgeführt wird?

$changes = [ 
      ['name' => 'Shirt', 'qty' => 1], 
      ['name' => 'Shorts', 'qty' => 1], 
      ]; 
$db->startTransaction(); 
foreach($changes as $change){ 
    $rowsUpdated = $db->exec("UPDATE inventory 
      SET reserved_quantity = reserved_quantity + $change['qty'] 
      WHERE product_name = $change['name'] 
       and quantity >= reserved_quantity + $change['qty']"); 
    if($rowsUpdated !== 1) 
     $db->rollback(); 
     exit; 
} 
$db->commit(); 

Ist es möglich, dass das Ergebnis sein wird?

[Shirt, 1, 2] 
[Shorts, 10, 2] 

Antwort

1

Es ist nicht. Mal sehen, was in dem folgenden Szenario würde geschehen:

  1. Die erste Transaktion beginnt
  2. UPDATEHemd => eine exklusive Zeilensperre wird auf der Platte
  3. eingestellt werden
  4. Die Sekunden Transaktion beginnt
  5. Die Sekunde Transaktion versucht UPDATEHemd. Wie es brauchen würde, eine Aufzeichnung zu erhalten, sperrt sie wie dieser Datensatz bereits von der ersten Transaktion
  6. Die erste Transaktion festgeschrieben wurde geschlossen warten würden, die Sekunden eine Ausführung wieder aufnehmen würde und sehen Sie die aktualisierten Datensatz

Natürlich ist es nur relevant für InnoDb und ähnliche mysql-Engines. Bitte beachten Sie, dass Sie das Glück haben, die Datensätze in der gleichen Reihenfolge zu durchlaufen. Wenn es nicht der Fall wäre, könnten Sie in eine deadlock

+0

Danke ffeast! Also ist die Zeilensperre vorhanden, bis die Transaktion nicht festgeschrieben oder rückgängig gemacht wird, auch wenn ich sie nicht explizit mit select for update benötige? – user3625393

+0

Ja http://dev.mysql.com/doc/refman/5.7/en/innodb-locks-set.html – ffeast

+0

Vielen Dank! Du hast recht. Ich habe gerade ein Prototyping gemacht und funktioniert wie beschrieben. – user3625393