Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Drzewa - Nested Sets, transakcje, lock tables
Black-Berry
post
Post #1





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


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?
Go to the top of the page
+Quote Post
webdice
post
Post #2


Developer


Grupa: Moderatorzy
Postów: 3 045
Pomógł: 290
Dołączył: 20.01.2007




Blokujesz tabele na początku edycji tabeli i odblokowujesz po.
Go to the top of the page
+Quote Post
Black-Berry
post
Post #3





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


a co jesli po 1 zapytaniu w calej polsce braknie pradu:)? 2 kolejne sie nie wykonają.
Go to the top of the page
+Quote Post
Cysiaczek
post
Post #4





Grupa: Moderatorzy
Postów: 4 465
Pomógł: 137
Dołączył: 26.03.2004
Skąd: Gorzów Wlkp.




To będziesz miał większe zmartwienia niż zła obsługa nested sets (IMG:http://forum.php.pl/style_emoticons/default/tongue.gif)
Go to the top of the page
+Quote Post
Black-Berry
post
Post #5





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


@Cysiaczek (IMG:http://forum.php.pl/style_emoticons/default/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
Go to the top of the page
+Quote Post
dr_bonzo
post
Post #6





Grupa: Przyjaciele php.pl
Postów: 5 724
Pomógł: 259
Dołączył: 13.04.2004
Skąd: N/A

Ostrzeżenie: (0%)
-----


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.
Go to the top of the page
+Quote Post
Black-Berry
post
Post #7





Grupa: Zarejestrowani
Postów: 663
Pomógł: 6
Dołączył: 3.06.2007
Skąd: Kraków

Ostrzeżenie: (0%)
-----


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".

Ten post edytował Black-Berry 30.12.2008, 16:41:09
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 20:46