ugrás a tartalomhoz

mySQL query ciklusban

chop · 2012. Feb. 4. (Szo), 20.34
Sziasztok!

Eléggé érthetetlen problémával állok szemben és már minden kombinációt kipróbáltam, mégsem jövök rá a megoldásra.

Adott az alábbi nagyon egyszerű kód:

$connect = new Mysqli('localhost','root','****','test');

for ($x = 0; $x <= 100; $x++) {
	$q = "INSERT INTO users VALUES('','".$x."')";
	$connect->query($q);
	echo $x.'. rekord beszúrva<br />';
}
A problémám az, hogy bár a ciklus rendesen lefut (a kimenetnél ez látszik is), azonban a táblába folyamatosan több rekordot tesz be a PHP, mint amennyit kellene. Gyakran van az, hogy elmegy szépen százig, aztán újrakezdik az iterációt 1-től és még bepakol 50-60 rekordot. Kipróbáltam OOP nélkül, simán mySQL-lel, mindig hibázik. Érthetetlen.

A tábla egy sima kétmezős tábla, egyikben auto_increment, primary key, a másik pedig int típusú.

Van tippetek?

Köszi.

(Tudom, hogy meg lehet csinálni ezt prepared statementtel és multiquery-vel is, de szerintem így is működnie kellene.)
 
1

Nem indokolt

janoszen · 2012. Feb. 4. (Szo), 20.42
Első ránézésre nem látom indokoltnak, hogy miért tenne be többet. Ugye kiürítetted a táblát, mielőtt próbálkoztál?

Más: az insert parancsnak lehet több rekordot is megadni, nem kell külön queryben beküldened.
2

Folyamatosan ürítem

chop · 2012. Feb. 4. (Szo), 20.48
Persze, truncate table megy állandóan, de folyamatosan ilyen a kimenet:


Olyan, mintha a cikluson belül elvesztené a fonalat, hogy éppen hol is jár. Próbáltam mysqli_free-t alkalmazni, de nem segített.
3

Csak tippelek:

Pepita · 2012. Feb. 4. (Szo), 21.01
- Ha az első mező az autoincrement, akkor neki nem tetszik az '' (=üres string) értékadás. Használj helyette NULL értéket. Vagy:
- Nevezd meg előbb (a VALUES előtt) a mezőket, aztán adj értékeket, így biztos, hogy abba a mezőbe kerül, amelyikbe szánod. (Bár elvileg ha nem adod meg, akkor a táblában levő elhelyezkedési sorrendben kellene mennie.)

Nem próbáltam, nekem még ilyen esetem nem volt...
4

Hmm...

chop · 2012. Feb. 4. (Szo), 21.08
Próbáltam mindkettőt, de sajnos nem ez a gond. Másrészt korábban csináltam már hasonlót és akkor semmi probléma nem volt. Érthetetlen.

Megpróbáltam másik adatbázis másik tábláján, az eredmény ugyanaz.
5

Akkor még egy,

Pepita · 2012. Feb. 4. (Szo), 21.57
ha már volt 1, 2, legyen egy x is:
- Én nem ismerem az adatbázismotort sem és a php értelmezőt sem eléggé ahhoz, hogy megítéljem, de arra (is) tippelnék, hogy a foreach ciklus "lehagyja" az adatbázismotort és a zűr valahol a folyamatok "naplózásánál" van. Pl. dolgozik az első INSERT, mire végére ér, a php az 5.-nél tart. Ezt rögtön átveszi MySql, de a közöttük lévők várakoznak. ... És ott a hiba, hogy a végén nem tudja, mennyi amit már megcsinált, hova kell visszamenni. Ebben bezavarhat neki az autoincrement cucc is, amiatt nem volna szabad 1. után 5.-et kezelnie, vagy akkor tudnia kell, hogy az az 5.

Igazából nem tudom, én még a BDE-vel voltam jobb ismeretségben.

Szerk.: lehet, hogy nagy hülyeséget írtam ide, ha igen: remélem valaki felhomályosít.
7

nem aszinkron

Raziel Anarki · 2012. Feb. 4. (Szo), 22.28
elvileg nem aszinkron a ->query(), megvárja mig lefut a query a DB-ben, és utána visszatér h sikeres volt-e, beállítja az affectedrows-t, errorkódot pl, stb
8

Köszi!

Pepita · 2012. Feb. 4. (Szo), 22.45
Így viszont jó lassú lehet...
9

PHP

Poetro · 2012. Feb. 4. (Szo), 22.54
A PHP ilyen. Egy szálon fut, és nagyon meg kell erőszakolni egyelőre, hogy ne így tegyen. Azaz a kódod mindig szinkron módon fog lefutni (ahogy szinte az összes programozási nyelvben).
10

Ezt gondoltam

Pepita · 2012. Feb. 4. (Szo), 23.22
A PHP-ről én is ezt gondoltam, lévén iterpreteres nyelv... Csak nem tartottam feltétlenül szükségesnek, hogy MySql-t megvárja. Bár jobban meggondolva nem is lehet másképp, mert "ő" interpreteres.
ahogy szinte az összes programozási nyelvben
Ezt ugye úgy érted, hogy alaphelyzetben? Remélem nem ment ki a divatból a thread-kezelés? (Bár én sem kényszerültem rá még soha.)
6

mod_rewrite?

Raziel Anarki · 2012. Feb. 4. (Szo), 22.19
mod_rewite-t esetleg használsz?

szokott olyan lenni, hogy ugye bejön az index.php, egy get paraméterben a lekért path-tel ha a file nem létezik...

a chorme pl. mindig két lekérdezést indít, a másikon lekéri a favicon.ico-t ugyanabból a mappából mint az url (és ha ilyen nincs, a mod_rewrite lefuttatja az index.php-t), lehet hogy ez zavar be?

(bár ekkor 2x100 db sor lenne, nem 1x100 + 50-60 db, bár attól függ hol a truncate)

csak tipp, ötlet, lehet hülyeséget mondok :)
11

Nincs mod_rewrite

chop · 2012. Feb. 5. (V), 11.13
Nem használok ilyesmit, szerintem is valami olyan probléma lesz, hogy nincs szinkronban a PHP és a mySQL.

Egyébként az a hihetetlen, hogy amennyiben csak egy iterációt csinálok, akkor is két rekordot szúr be a táblába!

Ha van valakinek ideje, akkor esetleg megnézhetné, hogy nála is ugyanezt csinálja-e.

Kivettem az auto_increment mezőt, akkor is rossz.
12

Kipróbáltam, és nálam úgy

Hidvégi Gábor · 2012. Feb. 5. (V), 11.19
Kipróbáltam, és nálam úgy működik a script, ahogy kell (PHP 5.3.9 és MySQL 5.5, Windows).

A MySQL-ben valahol van egy bináris vagy query log, azt, ha lehet, nézd meg szerintem, hogy milyen lekérdezések futnak le egymásután.
14

SQL

chop · 2012. Feb. 5. (V), 11.39
Tuti, hogy az SQL-ben van a hiba, mert ha összefűzom a query-ket és úgy küldöm el az adatbázisnak, akkor is elrontja, de ekkor már következetesen két rekordot szúr be egy helyett.

Hol találom ezt a logfile-t?
16

MySQL Server Logs

Hidvégi Gábor · 2012. Feb. 5. (V), 12.40
13

commit?

H.Z. v2 · 2012. Feb. 5. (V), 11.36
Hiányolom a programból a commitot. Nem lehet, hogy ki van kapcsolva az autocommit és ez okozza a kavarodást? (csak találgatok, elvileg nem lenne szabad ilyesmit okozniat)
Illetve B tipp: nem kísérleteztél triggerekkel és felejtettél ott egyet?
15

Egyik sem

chop · 2012. Feb. 5. (V), 11.43
Nem, egyik sem, legalábbis nem tudok róla. Tranzakciókkal nem foglalkoztam ebben a táblában, triggerekkel meg pláne nem.

Most alakítottam a táblán, egyik mezőbe mennek az X. értékek, másikba egy timestamp, az eredmény pedig valami ilyesmi 10 iteráció után:

1 1328434599
2 1328434599
3 1328434599
4 1328434599
5 1328434599
6 1328434599
7 1328434599
8 1328434599
9 1328434599
10 1328434599
1 1328434600
2 1328434600
3 1328434600
4 1328434600
5 1328434600
6 1328434600
7 1328434600
8 1328434600
9 1328434600
10 1328434600

--------------------
20 rows in set (0.00 sec)

Rejtély vagy rejtély?:)
17

timestamp másodperc alapú

Raziel Anarki · 2012. Feb. 5. (V), 15.07
timestamp másodperc alapú, én a php microtime(true)-t javaslom az float-ot ad, pontosabban (ezredmásodperc vagy pontosabb, nemtom konkrétan).

elv ez úgy néz ki mintha 2x futna a php-d, inzertálj a legelejen és a végén is vmit h biztos legyen.
18

interaktív PHP?

H.Z. v2 · 2012. Feb. 5. (V), 15.17
Hogy futtatod a programot? Interaktívan vagy web szerverből?
Ha utóbbi, akkor próbáld ki az interaktív verziót is, kihagyva az egészből az apace-t (vagy amilyen web szervert használsz)!
19

Érdekes fejlemény

chop · 2012. Feb. 5. (V), 19.57
Kíváncsiságból lefuttattam Explorerből is a szkriptet és láss csodát: megfelelően működik...sőt, Safariból is megy.

Úgyhogy akkor valóban az lesz a gond, amit írtál: a mod_rewrite. A kérdés az, hogy ez miért van egyáltalán, mikor nem index.php a file neve, hanem teljesen más, ráadásul semmilyen paramétert nem kap a file, amiben a lekérdezés van.

Ahogy nézem, ez nem is igazán webszerver probléma lesz, mert az eredeti problémám is megoldódott azzal, hogy Safariban szúrom be a rekordokat. A kérdés az, hogy a Chrome-mal mit lehet kezdeni, hogy ne csináljon ilyet?
21

Úgy saccolom, ennek nem sok

H.Z. v2 · 2012. Feb. 5. (V), 20.26
Úgy saccolom, ennek nem sok köze lehet a mod_rewrite-hoz.
Amennyire tudom, a chrome-ban van valami olyan funkció, ami gyorsítani próbálja az oldalak betöltődését azzal, hogy az oldalon lévő linkek tartalmát előre letölti. Inkább arra tippelnék, hogy ez a funkció kavar be neked, mert nincs a lapon tisztességes session management, viszont van mondjuk egy link önmagára.
Persze hangsúlyozom, ez csak tipp.
22

Annyi van a lapom, amit

chop · 2012. Feb. 5. (V), 20.52
Annyi van a lapom, amit bemásoltam, ezért is nehéz a debugging. Egyszerűen nincs, ami elromoljon, mivel csak ennyit tartalmaz a lap, amit beírtam.
24

errordocument esetleg?

Raziel Anarki · 2012. Feb. 5. (V), 21.45
ha azt is az index.php szolgálja ki a nemlétező favicon.ico-ra?
25

Ha be van kapcsolva a

Hidvégi Gábor · 2012. Feb. 5. (V), 22.37
Ha be van kapcsolva a mod_rewrite, akkor nézd meg a rewrite logot, hátha abból kiderül valami.
20

Másrészt az azért jól érzem,

chop · 2012. Feb. 5. (V), 20.22
Másrészt az azért jól érzem, hogy amikor ilyen tömeges beszúrás van, akkor érdemesebb összeszedni PHP-val a teljes stringet és végül az egészet elküldeni egy query-vel?

Gondolom ez azért gyorsabb is, másrészt alapból jobb választásnak tűnik egyben odaadni a teljes adagot a mysql-nek, mint folyamatosan hívogatni (pl. a user leállítja a lekérést és akkor a maradék query - gondolom én - elveszik).
23

igen, de

Raziel Anarki · 2012. Feb. 5. (V), 21.44
vigyázz mert van egy query buffer length, aminél nem lehet hosszabb a query. ezt vagy mysql_ből állítod (my.ini), php-ből hirtelen nem is tudom hol lehet...

egy gyors google ezt dobta: elv kliens (php) és szerver is állítja a max_allowed_packet változót, a default 16M.

http://dev.mysql.com/doc/refman/5.0/en/packet-too-large.html
26

16M

chop · 2012. Feb. 5. (V), 23.39
Köszi a tippet.