Nejste přihlášen(a)
Ahoj,
nová verze inTrancaction() (http://github.com/…fcfeddfd11f6)
mi na MySQL (InnoDB) pořád vrací TRUE, ať jsem v transakci nebo ne.
Dělal jsem pokus přímo v MySql command line a SELECT
@@autocommit; mi pořád vrací 1. Tento select se používá i uvnitř
metody inTrancaction(), takže tady bude asi ten zádrhel. Nevíte
co dělám špatně?
Děkuji Michal
PS: Výpis pokusu:
C:\mysql\bin>mysql.exe --user=root -p
Enter password: *********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 364
Server version: 5.1.41 Source distribution
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> USE xxxxx;
Database changed
mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
mysql> INSERT INTO cardtree (lft, rgt) VALUES (0,700);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM cardtree;
+----+-----+-----+
| id | lft | rgt |
+----+-----+-----+
| 48 | 3 | 16 |
| 50 | 6 | 7 |
| 51 | 8 | 9 |
| 52 | 10 | 11 |
| 53 | 12 | 13 |
| 54 | 14 | 15 |
| 70 | 0 | 700 |
+----+-----+-----+
7 rows in set (0.00 sec)
mysql> ROLLBACK;
Query OK, 0 rows affected (0.05 sec)
mysql> SELECT * FROM cardtree;
+----+-----+-----+
| id | lft | rgt |
+----+-----+-----+
| 48 | 3 | 16 |
| 50 | 6 | 7 |
| 51 | 8 | 9 |
| 52 | 10 | 11 |
| 53 | 12 | 13 |
| 54 | 14 | 15 |
+----+-----+-----+
6 rows in set (0.00 sec)
mysql> SELECT @@autocommit;
+--------------+
| @@autocommit |
+--------------+
| 1 |
+--------------+
1 row in set (0.00 sec)
Hlásím stejný problém jak v nejnovějším dibi, tak v revizi 0b95624 released on 2010–02–24, kde je způsob získáváni informace o transakci z mysql trochu odlišný.
// nejnovejsi
$row = mysqli_fetch_row(mysqli_query($this->connection, 'SELECT @@autocommit'));
return (bool) $row[0];
// 0b95624 released on 2010-02-24
return (bool) mysqli_fetch_field_direct(mysqli_query($this->connection, 'SELECT @@autocommit'), 0);
Mea culpa, že jsem funkci inTransaction() vůbec do dibi vracel :-)
Otevření transakce bohužel detekovat nejde, inTransaction() jsem zrušil.
Teroreticky by to slo implementovat jako priznak: dibi::begin() nastavi true a dibi::commint() nebo dibi::rollback() nastavi false. Bohuzel to ale nebude fungovat kdyz nekdo posle prikaz rucne primo bez dibi.
Osobne bych to vyuzil v pripadech kdy mam vice komponent v sobe a nektere pouzivaji transakce a jine ne. Osetrovat to pomoci vyjimky je dost nesikovne.
Dalsi moznost jak to vyresit je pouzivat savepoints coz dibi podporuje, ale mel jsem s itm nekde problemy. Uz nevim presne.
Tak se to testovalo kdysi, ale na to se nelze spolehnout, existují příkazy implicitně způsobující commit atd. Navíc mám za to, že použití inTransaction() svědčí o špatném návrhu aplikace ;)
A jak by se to tedy melo resit?
Napr: Mam univerzalni metodu v Modelu ktera se mi stara o upraveni dat ve vazebni tabulce M:N. Vpodstate ji reknu jak to ma vypadata a ona si sosne aktualni stav, chybejici doplni, prebyvajici smaze. Aby to vse bylo OK je to v transakci.
Jenze co kdyz tuto metodou pouziju v nejake slozitejsi update DB, ktera taky musi byt v transakci? Druhou transakci nastartovat nejde → vyjimka.
Tudis jsem nucen tuto vyjimku zachytit v one metode na upravu M:N a pokud ji zachytim tak neukoncovat transakci, protoze ja ji nezacal. Funkcni to je, jen je ten kod neelegantni oproti podmince s dibi::inTransaction().
Buď tak, že metodě řekneš, zda má použít transakci (třeba s výchozí hodnotou TRUE), nebo použiješ savepoint.
metodě řekneš, zda má použít transakci (třeba s výchozí hodnotou TRUE)
to je dost nepohodlne a spis tohle svedci o prapodivnem navrhu aplikace, ne? respektive rozhodnuti o transakci by snad melo byt uvnitr metody (chovani by melo byt precejen trosku blbuvzdorne a ne zavisle na tom, co tam nejaky programator soupne za hodnotu v patek vecer)
nebo použiješ savepoint
to by musely savepointy fungovat :D (mam MySQL 5.1.neco a ne a ne to sprovoznit s dibi)
navic stale plati, ze musim spustit transakci START TRANSACTION
a pak ji celou commitnout COMMIT… metoda
inTransaction() pak v modelove tride dovolila se rozhodnout,
jestli zahajit celou novou transakci / cele to na konci commitnout/rollbacknout,
nebo jen pridat savepoint do jiz existujici transakce.
nejak me nenapada, jak to ted, bez inTransaction spachat –
tak, aby byly modelove tridy nezavisle na nejakem nastaveni zvenci, popripade
kdyz modelovou tridu pouziju v jine modelove tride apod.
Editoval wdolek (13. 7. 2010 19:21)