Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP[MySQL] REASON: Deadlock found when trying to get lock; try restarting transaction
Forum PHP.pl > Forum > PHP
Jarod
Na wstępie napiszę, że baza develop to 5.0.21 a na serwerze 5.0.68.
Mam dosyć nietypowy problem i nie mogę znaleźć przyczyny błędu ani rozwiązania.


Problem występuje w jednej z części aplikacji i dotyczy jednej tabeli. Jej struktura jest następująca:
Kod
CREATE TABLE oceny
(
oceny_id INT NOT NULL AUTO_INCREMENT,
numer_pracownika INT NOT NULL,
data DATE NOT NULL,
ocena VARCHAR(1000),
account_id INT NOT NULL,
PRIMARY KEY(oceny_id),
UNIQUE(numer_pracownika, data),
INDEX(numer_pracownika, data),
CONSTRAINT FOREIGN KEY(numer_pracownika) REFERENCES wtr_pracownicy(numer_pracownika),
CONSTRAINT FOREIGN KEY(account_id) REFERENCES accounts(account_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



Controller:

  1. <?php
  2. require_once('Core/Cube/FrontController/Action.interface.php');
  3.  
  4. class CreateEmployeesSheetAction implements Action
  5. {
  6.    private $aToken;
  7.    private $iDay;
  8.    private $iMonth;
  9.    private $iYear;
  10.    private $bIsCorrectly = false;
  11.    
  12.    
  13.    public function __construct($aToken)
  14.    {
  15.              // waliduje dane i jęsli wszystko jest ok $this->bIsCorrectly = true, w przeciwnym razie przekierowuje
  16.    }
  17.    
  18.    
  19.    public function run()
  20.    {
  21.        if ($this->bIsCorrectly)
  22.        {
  23.            require_once(Config::$MVCModelsPath . '/CreateEmployeesSheetModel.class.php');
  24.            
  25.            $oCreateEmployeesSheetModel = new CreateEmployeesSheetModel();
  26.            $oCreateEmployeesSheetModel->create($this->iYear . '-' . $this->iMonth . '-' . $this->iDay);
  27.            
  28.            CubeFrontController::redirect(Config::$SystemPath . 'main/pl/EmployeesGradeViewAction/date/' . $this->iYear . '-' . $this->iMonth . '-' . $this->iDay);
  29.        }
  30.        else
  31.        {
  32.            CubeFrontController::redirect(Config::$SystemPath . 'main/pl/EmployeesGradeViewAction');
  33.        }
  34.    }
  35. }
  36. ?>



Model:
  1. <?php
  2. class CreateEmployeesSheetModel
  3. {
  4.    private $oRegistry;
  5.    private $oConnection;
  6.    
  7.    
  8.    public function __construct()
  9.    {
  10.        $this->oRegistry = CubeRegistry::getInstance();
  11.        $this->oConnection = $this->oRegistry->get('oDatabase');
  12.    }
  13.    
  14.    
  15.    public function getEmployeesId()
  16.    {
  17.         // zwraca tablicę z numerami pracowników
  18.    }
  19.    
  20.    
  21.  
  22.    public function create($sDate)
  23.    {
  24.        $this->oConnection->query('SELECT count(pax_oceny_id) As count FROM pax_oceny WHERE data='' . $sDate . ''');
  25.        $iNumberOfResult = $this->oConnection->fetchAll();
  26.        
  27.        if ($iNumberOfResult[0]['count'] == 0)
  28.        {
  29.            $this->oConnection->startTransaction();
  30.            $tab = array();
  31.  
  32.            foreach($this->getEmployeesId() As $aEmployeesId)
  33.            {
  34.                $this->oConnection->query('INSERT INTO oceny VALUES (NULL, ' . $aEmployeesId['numer_pracownika'] . ', '' . $sDate . '', NULL, '' . $_SESSION['AccountId'] . '')');
  35.            }
  36.            $this->oConnection->commitTransaction();
  37.            
  38.        }
  39.    }
  40. }
  41. ?>



PROBLEM: W losowych momentach skrypt wywala błąd, zatrzymuje swoje wykonywanie i do pliku z logami dostaję taki zapis:
Cytat
EXCEPTION: Nieudane zapytanie: INSERT INTO oceny VALUES (NULL, 173, '2008-11-4', NULL, '1')
REASON: Deadlock found when trying to get lock; try restarting transaction


Problem ciężki do zdiagnozowania ponieważ dzieje się to z różnych momentach. Tzn raz skrypt mogę wywołać 30 razy wszystko jest ok a innym razem przy drugim wywołaniu wywala błąd.
Testuję na lokalnym serwerze, podczas testów na programie pracuje tylko jedna osoba.

Proszę o jakieś wskazówki, rady.

Pozdrawiam
Riklaunim
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html

Transakcja może zablokować dostęp do tabeli, lub jej części, przez co kolejne zapytanie natrafiające na zablokowaną tabelę wyłoży się.
Jarod
Cytat(Riklaunim @ 30.11.2008, 14:47:25 ) *
http://dev.mysql.com/doc/refman/5.0/en/innodb-deadlocks.html

Transakcja może zablokować dostęp do tabeli, lub jej części, przez co kolejne zapytanie natrafiające na zablokowaną tabelę wyłoży się.

O tym to wiem - sam się przekonałem.
Jak sobie z tym najlepiej poradzić? Zamiast transakcji stosować blokowanie table?
Riklaunim
ponawiać transakcję odpowiednio - doczytaj o tym, szczegółów nie znam winksmiley.jpg
dr_bonzo
Hmm, ciekawe. Mowisz ze jedna tylko aplikacja w danym czasie ma dostep do bazy? Do tego masz jedna transakcje i tworzy ci deadlocki?
Jarod
Cytat(dr_bonzo @ 30.11.2008, 15:25:38 ) *
Hmm, ciekawe. Mowisz ze jedna tylko aplikacja w danym czasie ma dostep do bazy? Do tego masz jedna transakcje i tworzy ci deadlocki?

Dokładnie.
Testuję to lokalnie (tylko ja jako jeden user). Wstawia kilkadziesiąt rekordów na wybrany dzień. Czyszczę tabelę (truncate) i po kolei na każdy dzień zaczynając np od 1.11.2008 klikam generuj arkusz (wtedy wykonywany jest skrypt), następnie wybieram kolejny dzień i znowu generuję.
Czasami na dacie drugiego listopada (czyli za drugim wywołaniem) czasami za 30stym wywołaniem pojawia się taki błąd.

EDIT:
------
Wskazówka: Po ściągnięciu unikalnego klucza UNIQUE(numer_pracownika, data) problem jak na razie nie wystąpił.

FINAL:
-------

Poświęciłem 2 dni na szukanie najpierw błędu w skrypcie, później przeglądałem listę bugów mysql'a, przekopałem pół google i żadnych sensownych wskazówek.
Zacząłem szukać przyczyny gdzie indziej. Mianowicie zauważyłem, że czasem oprócz błędu o zakleszczeniu transakcji równocześnie albo na przemian pojawia się błąd:
Cytat
Duplicate entry '173-2009-03-02' for key 2

Podczas wstawiania rekordów do bazy, zacząłem zapisywać równocześnie do pliku numery pracowników i gdy pojawił się błąd natychmiast przeglądałem plik w poszukiwaniu niby powtórzonych rekordów - ale takie nie występowały.

Pomyślałem, że albo to błąd w php 5.2.0 (coś nie tak z pętlą foreach) albo przeglądarka. Sprawdziłem w Operze - jest ok.
Błędy występuję od wersji 3.x (na pewno 3.0.0 i 3.0.4). Oczywiście to są tylko moje przypuszczenia bo muszę to jeszcze dokładnie przetestować (sprawdzić na nowszym php, sprawdzić na starszych przeglądarkach FF 2.x).

Jestem ciekawy czy ktoś z Was zetknął się z podobnym problemem? Jak się upewnię co do tej przeglądarki to dam znać.
Pzdr.


EDIT:
------
Problem w przeglądarce Firefox 2.0.0.14 nie występuje.
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.