tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

Transakce a firebird

před 9 lety

wotaen
Člen | 82

Ahoj všichni, mám problém s transakcema ve firebirdu. Používám firebird driver od Romana Sklenáře firebird.php…problém je následující
Mám třídu X, privátní property $connection, která se naplní při vytváření instance

<?php
$this->connection = dibi::getConnection();
?>

Třída X má dvě metody, read a write.

<?php
function write($test)
        try {
            $this->connection->begin();
            $this->connection->update('tests',array(
               'taken'      => count($test->sentences),
               'percentage' => $test->getPercentage()
            ))
            ->where('id=%i',$test->id)
            ->execute();
            }
            $this->connection->commit();
        } catch (Exception $exception) {
            $this->connection->rollback();
            throw $exception;
        }
?>

a metoda read je prosté

<?php
$this->connection->query('nacti posleni aktualizovany test');
?>

Problém je v tom, že když zavolám write a následně read, tak read nevidí změny provedené writem. Pokud odstraním transakci z write (begin a commit), tak vše najednou jede jak má.
Je možné že to ani nemá souvislost s dibi či driverem od Romana…ale už jsem v koncích.

Díky, Michal

Editoval wotaen (11. 2. 2010 11:52)

před 9 lety

romansklenar
Člen | 657

Pár věcí mě napadá:

  • nepoužíváš tam třeba někde savepointy?
  • nemůže se stát, že transakce zůstane otevřená?
  • nesouvisí to s problémem souběhu transakcí a jejich izolací?

Protože takový kus kódu, který jsi tu dal nám v projektu funguje (i se savepointy) bez problémů.

před 9 lety

wotaen
Člen | 82

romansklenar napsal(a):

Pár věcí mě napadá:

  • nepoužíváš tam třeba někde savepointy?
  • nemůže se stát, že transakce zůstane otevřená?
  • nesouvisí to s problémem souběhu transakcí a jejich izolací?

Protože takový kus kódu, který jsi tu dal nám v projektu funguje (i se savepointy) bez problémů.

V rámci čitelnosti jsem ten vkládaný kód ořezal…možná to bylo na škodu věci. Teď jsem doma a nemám u sebe kód, mrkmu na to v pondělí, ale z hlavy se problém projevuje následovně…

Nejprve zavolám read($test), v test se volá ‚select * from generate_test(xxx)‘ a procedura generate_test vytvoří nový test (jeden záznam v tabulce X a 6 záznamů v tabulce Y, navíc je procedure selectable a po každém insertu do Y je suspend) a vrátí id a nějaké další data z Y. Pokud dám po vykonání ‚vyber posledne vlozeny test‘ tak se to vybere. Ale v případě, že je první select obalený transakcí, tak druhý už nic nevrátí (i přestože na první jsem zavolal commit). Související problém asi bude, že když první select (generate_test) je v transakci a druhým query smažu test, tak mi to hodí deadlock, že je otevřená transakce…ale jak to?! Vždyť jsem ji zavřel.
Myslím, že problém asi opravdu bude v tom, že transakce při prvním selectu se nezavře (i přestože jí to řeknu), ale proč, nechápu. Savepointy, asi, nepoužívám, resp. firebird.php je nepoužívá. Při ibase_trans jsem zkoušel všechny možné typy izolací, ale ani jedno nevedlo ke kýženému výsledku.
Pokud tě nic nenapadne, nebo to celé zní příliš obecně, tak v pondělí vložím kus opravdového kódu.

Dík, Michal

před 9 lety

wotaen
Člen | 82

Sypu si popel na hlavu, problém byl v tom, že jsem měl ještě někde jinde update, který běžel v defaultní php transakci a tím pádem update z jiné transakce skončil deadlockem :(