Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision e852b156

Von Moritz Bunkus vor etwa 9 Jahren hinzugefügt

  • ID e852b156652474de1b5cb4b12b1a08d4954f69a6
  • Vorgänger 77c9e010
  • Nachfolger 46990042

SL::DB::Helper::TransNumberGenerator: Tabellen und Zeilen locken

Die Tabelle, aus der die Liste der bereits benutzten Belegnummern
ausgelesen wird, muss exklusiv gelockt werden, um zu verhindern, dass
danach zwischen dem Auslesen und der Vergabe der neuen Belegnummer eine
andere DB-Verbindung dasselbe macht und dieselbe Nummer verwendet.

Dieses Locking muss daher vor dem Auslesen der Daten geschehen.

Weiterhin müssen die Zeilen in den Nummernkreistabellen (defaults
bzw. business) gelockt werden. Hier reicht aber das Locking der
entsprechenden Zeile.

Beide Locks müssen analog zu SL::TransNumber gehandhabt werden, um einen
potenziellen Deadlock zu vermeiden, sprich zuerst die Belegtabelle,
danach die Zeile in der Nummernkreistabelle.

Unterschiede anzeigen:

SL/DB/Helper/TransNumberGenerator.pm
70 70
    }
71 71
  }
72 72

  
73
  # Lock both the table where the new number is stored and the range
74
  # table. The storage table has to be locked first in order to
75
  # prevent deadlocks as the legacy code in SL/TransNumber.pm locks it
76
  # first, too.
77

  
78
  # For the storage table we have to use a full lock in order to
79
  # prevent insertion of new entries while this routine is still
80
  # working. For the range table we only need a row-level lock,
81
  # therefore we're re-loading the row.
82
  $self->db->dbh->do("LOCK " . $self->meta->table) || die $self->db->dbh->errstr;
83

  
73 84
  my %numbers_in_use = map { ( $_->$number_column => 1 ) } @{ $self->_get_manager_class->get_all(%conditions_for_in_use) };
74 85

  
75
  my $range_table    = $business ? $business : SL::DB::Default->get;
86
  my $range_table    = ($business ? $business : SL::DB::Default->get)->load(for_update => 1);
87

  
76 88
  my $start_number   = $range_table->$number_range_column;
77 89
  $start_number      = $range_table->articlenumber if ($number_range_column eq 'assemblynumber') && (length($start_number) < 1);
78 90
  my $sequence       = SL::PrefixedNumber->new(number => $start_number // 0);

Auch abrufbar als: Unified diff