Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision a4b8c277

Von Bernd Bleßmann vor 3 Monaten hinzugefügt

  • ID a4b8c27747a33fc3d480f95d1cee0067e4e63321
  • Vorgänger ec57bf69
  • Nachfolger efa419f3

Csv-Import: Referenzierte Tabellen locken, wenn TransNumberGenarator …

… verwendet wird.

Wenn der Importer in Tabellen speichert, die Nummern über den
TransNumberGenerator erhalten können, dann müssen auch von diesen
Tabellen referenzierte Tabellen, die Nummern über den TransNumberGenerator
erhalten können, gelockt werden.
Andernfalls kann es zu einer Verklemmung kommen, wenn jemand an der Oerfläche
einen Beleg speichern möchte.

WEB: sperrt Zieltabelle (z.B. ar für Rechnungen)
Importer: sperrt oe (für Aufträge) (*)
Importer: sperrt defaults
WEB: will defaults sperren > warten
Importer: will oe speichern, muss dazu aber auch die referenzierten Tabellen
locken (hier z.B. ar). ar ist gelockt -> warten
> deadlock

(*) wenn hier auch referenzierte Tabellen (ar im Beispiel) gesperrt werden,
dann ist alles ok, da der Importer dann wartet, bevor er die defaults sperrt.

Unterschiede anzeigen:

SL/Controller/CsvImport/Base.pm
534 534
  return unless $data->[0];
535 535
  return unless $data->[0]{object};
536 536

  
537
  # If we store into tables which get numbers from the TransNumberGenerator
538
  # we have to lock all tables referenced by the storage table (or by
539
  # tables stored alongside with the storage table) that are handled by
540
  # the TransNumberGenerator, too.
541
  # Otherwise we can run into a deadlock if someone saves a document via
542
  # the user interface. The exact behavoir depends on timing.
543
  # E.g. we are importing orders and a user want to
544
  # book an invoice:
545
  # web: locks ar (via before-save hook and TNG (or SL::TransNumber))
546
  # importer: locks oe (via before-save hook and TNG) (*)
547
  # importer: locks defaults (via before-save hook and TNG)
548
  # web: wants to lock defaults (via before-save hook and TNG (or SL::TransNumber)) -> is waiting
549
  # importer: wants to save oe and wants to lock referenced tables (here ar) -> is waiting
550
  # --> deadlock
551
  #
552
  # (*) if the importer locks ar here, too, everything is fine, because it will wait here
553
  # before locking the defaults table.
554
  #
555
  # List of referenced tables:
556
  # (Locking is done in the transaction below)
557
  my %referenced_tables_by_type = (
558
    orders          => [qw(ar customer vendor)],
559
    delivery_orders => [qw(customer vendor)   ],
560
    ar_transactions => [qw(customer)          ],
561
    ap_transactions => [qw(vendor)            ],
562
  );
563

  
537 564
  $self->controller->track_progress(phase => 'saving data', progress => 0); # scale from 45..95%;
538 565

  
539 566
  my $last_index = $#$data;
......
542 569
  for my $chunk (0 .. $last_index / $chunk_size) {
543 570
    $self->controller->track_progress(progress => ($chunk_size * $chunk)/scalar(@$data) * 100); # scale from 45..95%;
544 571
    SL::DB->client->with_transaction(sub {
572

  
573
      foreach my $refs (@{ $referenced_tables_by_type{$self->controller->{type}} || [] }) {
574
        SL::DB->client->dbh->do("LOCK " . $refs) || die SL::DB->client->dbh->errstr;
575
      }
576

  
545 577
      foreach my $entry_index ($chunk_size * $chunk .. min( $last_index, $chunk_size * ($chunk + 1) - 1 )) {
546 578
        my $entry = $data->[$entry_index];
547 579

  

Auch abrufbar als: Unified diff