tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

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

Vyčerpání paměti při vkládání binárních dat do MySQL

před 10 lety

m0t3jl
Člen | 293

Ahoj,
mám takový problém u jednoho skriptu, který vkládá binární data do MySQL. V tom skriptu mám foreach
nad soubory v rámci jednoho adresáře. Ty soubory postupně čtu přes file_get_contents a potom je pomocí INSERTu (s použitím %bin) vkládám do databáze. Těch souborů je sice cca 4K, ale největši z nich má 1,2 MB.

Někde kolem 1,4Ktého souboru skript exne s chybou, že už nelze alokovat další paměť (konkrétně to je vždy, když MySQL driver volá mysql_real_escape_string nad těmi binárními daty.

Už jsem si v php.ini navyšoval množství paměti, které může skript sníst, ale ani 128MB není dost, takže se někde musí něco dít špatně.

Ten foreach vypadá následovně:

<?php
foreach($dirItems as $item)
{
  $itemContents = file_get_contents($item);
  $query = 'INSERT INTO [prilohy] ([data]) VALUES(%bin)';
  dibi::query($query, $itemContents);
}
?>

Zkoušel jsem přidávat i unset($query) a unset($itemContents) jako poslední řádek do toho foreache, ale nemělo to žádný efekt. Když si třeba jen nechám vyechovat $itemContents, tak k žádnému přetečení paměti nedojde. Profiler dokonce tvrdí, že v se zabralo jen 7 105,5 kB (což i tak je docela hodně, ale myslím, že to dělá použité Nette).

Děkuji mockrát za jakékoliv postrčení.

Editoval m0t3jl (29. 6. 2009 16:24)

před 10 lety

onge
Člen | 53

ono neco taky zere to spojeni s databazi, unsetovanim query tomu urcite nepomuzes. Rekl bych, ze stejne by to dopadlo i v pripade volani cisteho mysql_query(mysql_real_escape_string($content)). Dalsi vec je, file_get_contents si nejspis bude drzet ukazatele na soubory (hadam).

Zkusil bych to brat po davkach – nejdriv prvni 1000, pak dalsi…

PS: jak dlouho trva, nez se vypise obsah 4000 souboru, pricemz nektere maji az 1.2MB ?

před 10 lety

m0t3jl
Člen | 293

onge napsal(a):

ono neco taky zere to spojeni s databazi, unsetovanim query tomu urcite nepomuzes. Rekl bych, ze stejne by to dopadlo i v pripade volani cisteho mysql_query(mysql_real_escape_string($content)). Dalsi vec je, file_get_contents si nejspis bude drzet ukazatele na soubory (hadam).

Zkusil bych to brat po davkach – nejdriv prvni 1000, pak dalsi…

PS: jak dlouho trva, nez se vypise obsah 4000 souboru, pricemz nektere maji az 1.2MB ?

Ono to unsetování query byl spíš takový debilní pokus ujistit se, že se všechno skutečně odstraní, i když se na to nic neodkazuje a mělo by se to udělat samo.

To čisté mysql_query schválně zkusím.

Co by jsi navrhoval použít místo file_get_contents?

Nelíbí se mi idea načítání po dávkách ;) I když ho beru jako poslední možnost.

Prostor pro diskuzi: Jak je vlastně možné, že i takový skript, který vlastně nic nikam do paměti neukládá, za svůj běh sežere tolik paměti ? ;).

před 10 lety

phx
Člen | 652

A co mysql_flush (popripade obdoba v dibi) nebo tak nejak. (nevim presne jak to je)

před 10 lety

m0t3jl
Člen | 293

phx napsal(a):

A co mysql_flush (popripade obdoba v dibi) nebo tak nejak. (nevim presne jak to je)

V tomhle ohledu mě napadá jen mysql_free_result(), případně použít mysql_unbuffered_query(), ale podle názvu i podle dokumentace to je spíš na SELECTové query ;), není mi jasné, co by si ta INSERTová pamatovala.

před 10 lety

phx
Člen | 652

Za pokud by to mozna stalo.

Dale me napada, ze by stalo za pokud to prepsat tak aby tam nebylo dibi. Zajimalo by me (a asi nejen me), zda to je chyba dibi nebo neceho jineho co dibi nemuze ovlivnit.

před 10 lety

David Grudl
Nette Core | 6806

Není tam třeba spuštěný dibi profiler?

před 10 lety

m0t3jl
Člen | 293

David Grudl napsal(a):

Není tam třeba spuštěný dibi profiler?

To je slovo do pranice ;) Sice si neukazuju Debug::enableProfiler(), ale při připojení do DB tam určitě mám profiler povolenej.

Pokud to ale dělá tohle, tak by to asi chtělo nějak ošetřit, ne?

před 10 lety

PetrP
Člen | 587

Dibi profiler se vypisuje do Firephp v Firubugu. Jako ošetření doporučuju profiler vypnout ;]

před 10 lety

m0t3jl
Člen | 293

PetrP napsal(a):

Dibi profiler se vypisuje do Firephp v Firubugu. Jako ošetření doporučuju profiler vypnout ;]

To jsem taky mohl napsat, že to fakt je skript, že to pouštím z konzole :).

před 10 lety

David Grudl
Nette Core | 6806

Přidal jsem profileru nějaký limit, aby nevyčerpal paměť.

před 10 lety

m0t3jl
Člen | 293

David Grudl napsal(a):

Přidal jsem profileru nějaký limit, aby nevyčerpal paměť.

S vypnutým profilerem databáze je vše ok. Myslím ale, že i to nastavení maximálního žraní paměti je dobré.