Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Drzewa - Nested Sets
Forum PHP.pl > Forum > Bazy danych
Black-Berry
Napisałem klasę obsługującą drzewka NS. W praktyce wszystko działa fantastycznie ale mam dylemat bo w teorii coś zawsze się może popsuć. Dla przykładu kod zamieniający ze sobą dwie sąsiednie gałęzie drzewa:
  1. <?php
  2. public function moveNodeRight($id)
  3. {
  4.    if ($currentNode = $this->_getNode($id)) {
  5.        $query = "SELECT $this->dbTableColumns FROM (.[*1].) IMIT 1";
  6.        $this->dbDriver->query($query);
  7.        $nextNode = $this->dbDriver->fetchRow();
  8.        if ($nextNode) {
  9.            $currentNodeElements = ($currentNode->right - $currentNode->left +1) / 2;
  10.            $restNodesElements = ($nextNode->right - $currentNode->right) / 2;
  11.            $this->dbDriver->query("UPDATE `$this->dbTable` SET `(.[*2].)` cluster");
  12.            $this->dbDriver->query("UPDATE `$this->dbTable` SET `(.[*3].) cluster");
  13.            $this->dbDriver->query("UPDATE `$this->dbTable` SET (.[*4].) `left` < 0");
  14.        }
  15.    }
  16. }
  17.  
  18. [*1] "SELECT $this->dbTableColumns FROM `$this->dbTable` WHERE `parentId` = $currentNode->parentId
  19.        AND `parentId` <> 0 AND `left` = $currentNode->right + 1 LIMIT 1"
  20. [*2] "UPDATE `$this->dbTable` SET `left` = (-1)*(`left` + ($restNodesElements*2)),
  21.        `right` = (-1)*(`right` + ($restNodesElements*2)) WHERE `left` >= $currentNode->left
  22.        AND `left` < $currentNode->right AND `cluster` = $currentNode->cluster"
  23. [*3] "UPDATE `$this->dbTable` SET `left` = (`left` - ($currentNodeElements*2)),
  24.        `right` = (`right` - ($currentNodeElements*2)) WHERE `left` > $currentNode->right
  25.        AND `left` < $nextNode->right AND `cluster` = $currentNode->cluster"
  26. [*4] "UPDATE `$this->dbTable` SET `left` = (-1)*(`left`), `right` = (-1)*(`right`) WHERE `left` < 0"
  27. ?>


Sam kod nie jest moze aż tak ważny. Istotne jest że są tam 3 "UPDEJTY" które muszą się wykonać zawsze w całości oraz żadne inne zapytanie typu UPDATE nie może się wykonać na tej tabeli pomiędzy tymi zapytaniami.

Próbowałem kilku sposobów ale chciałbym się poradzić kogoś z większym doświadczeniem bo nigdy wcześniej nie korzystałem z lock tables ani transakcji. W jaki sposób powinienem je w tym wypadku zastosować ? Moze dla nested sets tree są jakieś utarte szlaki?
webdice
Blokujesz tabele na początku edycji tabeli i odblokowujesz po.
Black-Berry
a co jesli po 1 zapytaniu w calej polsce braknie pradu:)? 2 kolejne sie nie wykonają.
Cysiaczek
To będziesz miał większe zmartwienia niż zła obsługa nested sets tongue.gif
Black-Berry
@Cysiaczek haha.gif Ale tak na poważnie, to kluczowa sprawa. Czy seria takich zapytań moze prowadzić do rozpadniecia sie struktury?

Link do strony testowej: http://www.edico.nazwa.pl/3.5/tree.php
dr_bonzo
ACID to ACID, transakcje sa na prawde atomiczne, zapis calej transakcji to jedna podstawowa operacja dyskowa (potwierdzajaca ze wszystkie juz wpisane rekordy ma traktowac jako aktualne, itp.) + dodatkowo datacentery maja awaryjne zrodla zasilania.
Black-Berry
Ok ale jak w raktyce powinienem to zrobic? Wystarczy ze ustawię typ tabeli na INNODB i przed procedurą wstawię begin a na końcu COMMIT? Czy powinienem stosować jakieś specjalne tagi np SELECT FOR UPDATE ?

Edit:
Coś mi się widzi że tu nikt nie korzysta z modelu "Nested Sets" bo wątek umarł. Zauważyłem że jest to duży problem dla PHP+mySQL. Testy wydajnościowe doprowadziły do zawieszenia bazy mySQL. (Na serwerach nazwa.pl wykorzystanie maksymalnego przydziału czasu procesora).

Wniosek nasuwa mi się tylko taki że nie warto używać modelu NS. Leprzy zwykły "Adjacency List".
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.