"Database refetch failed; row with signature ‚601‘ does not exist!
- Pepiik
- Člen | 10
Ahoj,
Na serveru se mi náhodně objevují chyby „Database refetch failed; row with
signature ‚xxx‘ does not exist!“ Půl dne laboruji kdy přesně to uděla
a zjistil jsem konkrétní postup kdy to vždy udělá.
Nette/Database 3.1.6 (dělalo to i na starších verzích)
- Vymaže se cache
- První request na server: Dotaz nad tabulkou activities nevrátí žádný výsledek
- Druhý request na server: Dotaz nad tabulkou activities vrátí nějaký výsledek, vleze to do foreache a nad zavoláním metody toArray() to hodí chybu.
- Pak už to chybu nikdy nehodí dokud se zase nesmaže cache.
$today = date('Y-m-d', time());
$late_activities = $this->database->table('activities')
->where('due_date < ?', $today)
->where('id_activity_state ?', 1)
->fetchAll();
foreach ($late_activities as $activity) {
$activity->update([ 'id_activity_state' => 3]);
$xx = $activity->toArray(); // Tady spadne s hláškou "Database refetch failed; row with signature '601' does not exist! "
}
Zkoumal jsem co se změní v cache a ve druhém requestu (kdy to hodí tu
chybu) se změní obsah u jednoho souboru.
z
000068a:2:{s:4:"time";s:21:"0.01619100 1671490756";s:10:"serialized";b:1;}a:1:{s:11:"id_activity";b:1;}
na 000068a:2:{s:4:"time";s:21:"0.66501100 1671490852";s:10:"serialized";b:1;}b:0;
Je to bug nebo vlastnost a mám to udělat jinak?
Díky
- nightfish
- Člen | 518
@Pepiik Počti si v těchto odkazech, třeba narazíš na něco nápomocného.
https://forum.nette.org/…es-not-exist
https://github.com/…e/issues/187
- Pavel Kravčík
- Člen | 1196
Stávalo se ve staré verzi, pak to David opravil. Možné rady:
- Upgrade Nette
- Explicitně vyjmenovat všechny sloupce v select (to nám pomohlo v jednom projektu)
- Zavolat dotaz znovu (pomohlo v jiném projektu), místo
$activity->toArray()
→$newSql->fetch()
- Kamil Valenta
- Člen | 820
Ano, často pomůže select s vyjmenovanými sloupci.
Ty si nejprve selectneš věty, které mají id_activity_state=1,
pak jim uděláš update na id_activity_state=3.
Pak třeba v nějakém ifu sáhneš na sloupec, který v původním selectu
nebyl zahrnut, tak se provede refetch, ale ten záznam při where
id_activity_state=1 už neexistuje, protože nyní má id_activity_state=3.
- Pepiik
- Člen | 10
Díky za odpovědi.
Chtěl jsem spíš více pochopit jak to funguje. Přidal jsem tam teda
navíc ještě ->select('*')
a už to nedělá.
@KamilValenta
Chápu co myslíš, ale tím nexistujícím řádkem po update to není.
Protože po změně té cache co jsem vypsal to funguje. Asi si to nějak
špatně při tom prvním requestu nacachuje strukturu viz ten rozdíl co jsem
posílal. Jakoby to nedokázalo rozeznat primarní klíč. Jak jsem tam přidal
navíc ten ->select('*')
, tak už se cache vygeneruje rovnou
tím druhým způsobem. Jinej kód tam není, testoval jsem to přesně na takto
jak jsem to poslal.
Je to takovej neuspokojivej fix, ale už se v tom dál babrat nebudu :D
Řešení:
$late_activities = $this->database->table('activities')
->select('*')
->where('due_date < ?', $today)
->where('id_activity_state ?', 1)
->fetchAll();
- Kamil Valenta
- Člen | 820
Pepiik napsal(a):
Chápu co myslíš, ale tím nexistujícím řádkem po update to není.
Dobře, jak myslíš.
Už jen tak mimo hru si můžeš zkusit přečíst tu exceptionu, kterou to
vykoplo a zamyslet se nad tím, z jakého důvodu ten row už
„neexistuje“.
A že řešení přineslo select(‚*‘), ale zrovna tak by stačilo udělat ten update až na konci (ovšem v tom poli by se ta hodnota na 3 musela změnit jinak).