Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: PHP nie usuwa starych danych z pamięci podczas zapytań MySQL
Forum PHP.pl > Forum > PHP
adbacz
W bazie danych jest coś koło 132 000 rekordów oraz ponad 140 tabel. Chcę stworzyć dump tej bazy danych w PHP. Wszystko działa poprawnie, tylko, że PHP nie usuwa danych z pamięci i gromadzi je w sobie, mimo, że juz z nich dawno nie korzystam.

Wartości sA przypisywane do zmiennych, które po skończeniu usuwam metodą unset(). Podczas pętli pod tabelach, na jej końcu wywołuje metodę memory_get_peak_usage(true), któa wskazuje mi stale rosnącą wielkość zajętej pamięci przez PHP.

Dodam tylko, że w trakcie tworzenia dump-u, zapytania są dzielone na kawałki po 5000 elementów, i zapisywane do pliku, po czym znowu jest zapisywane do zmiennej 5000 elementów i zapisywane do pliku. Za każdym razem ta zmienna, w której znajdywała się treść tych zapytań też jest usuwana metodą unset(). Mimo to, ilośc zajętej pamięci stale rośnie.

PHP 5.3.10

Dwie metody pobierania danych z bazy: czyste zapytania poprzez funkcję mysql_query oraz przez PDO. W obu przypadkach wstępuje ten sam problem.
phpion
Próbowałeś zmniejszyć paczkę z 5000 do np. 500? I czy faktycznie przekracza pamięć czy limit czasu wykonania?
adbacz
Zmniejszałem paczki, ale wszystko zostaje w pamięci. A zmniejszenie paczek zwiększa tylko czas na wygenerowanie pełnej kopii bazy.

@nospor - użyłem mysql_free_result(), oraz dla PDO - PDO::closeCursor() ale to nic nie daje.
nospor
Wiesz, teraz to my jedynie możemy wróżyć z fusów.... Pokaż kod, to będziemy mogli konkretnie pogadać.
adbacz
Cała treść metody z klasy, w której znajduje się.

  1. file_put_contents(BASEPATH.'/Cache/dump.sql', '');
  2.  
  3. $tables = $this->db->query('SHOW TABLE STATUS')->fetchAll();
  4.  
  5. for($i=0, $count=count($tables); $i<$count; $i++)
  6. {
  7. $result = $this->db->query('SHOW CREATE TABLE `'.$tables[$i]['Name'].'`');
  8. $createTableQuery = $result->fetchAll();
  9.  
  10. if(isset($createTableQuery[0]['Create Table']))
  11. {
  12. $tablesDefinitions = $createTableQuery[0]['Create Table'].";\n\r\n\r\n\r\n\r";
  13. }
  14. else
  15. {
  16. $table = $this->db->query('SHOW COLUMNS FROM `'.$tables[$i]['Name'].'`')->fetchAll();
  17.  
  18. $tablesDefinitions = 'CREATE TABLE IF NOT EXISTS `'.$tables[$i]['Name'].'` ('."\r\n";
  19.  
  20. $primary = '';
  21.  
  22. for($j=0, $countj=count($table); $j<$countj; $j++)
  23. {
  24. if(!empty($tablecontent) && strpos($tables[$i]['Name'], 'backup') === false)
  25. {
  26. $valuesDefinitions .= '`'.$table[$j]['Field'].'`, ';
  27. }
  28. $tablesDefinitions .= '`'.$table[$j]['Field'].'` '.$table[$j]['Type'].' COLLATE '.$tables[$i]['Collation'].' '.($table[$j]['Null'] == 'YES' ? 'NULL' : 'NOT NULL').(($table[$j]['Default'] != '' && $table[$j]['Default'] != null) ? ' DEFAULT \''.$table[$j]['Default'].'\'' : '').($table[$j]['Extra'] == 'auto_increment' ? ' AUTO_INCREMENT' : '').",\r\n";
  29.  
  30. if($table[$j]['Key'] != '')
  31. {
  32. if($table[$j]['Key'] == 'PRI')
  33. {
  34. $primary .= ', PRIMARY KEY (`'.$table[$j]['Field'].'`)';
  35. }
  36. elseif($table[$j]['Key'] == 'UNI')
  37. {
  38. $primary .= ', UNIQUE KEY `'.$table[$j]['Field'].'` (`'.$table[$j]['Field'].'`)';
  39. }
  40. elseif($table[$j]['Key'] == 'MUL')
  41. {
  42. $primary .= ', KEY `'.$table[$j]['Field'].'` (`'.$table[$j]['Field'].'`)';
  43. }
  44. }
  45. }
  46.  
  47. $tablesDefinitions = substr($tablesDefinitions, 0, strlen($tablesDefinitions)-3);
  48.  
  49. $tablesDefinitions .= $primary."\r\n".') ENGINE='.$tables[$i]['Engine'].' DEFAULT COLLATE='.$tables[$i]['Collation'].' '.(isset($tables[$i]['Auto_increment']) ? 'AUTO_INCREMENT='.$tables[$i]['Auto_increment'] : '').' ;'."\r\n\r\n\r\n";
  50. }
  51.  
  52. $result->closeCursor();
  53.  
  54. file_put_contents(BASEPATH.'/Cache/dump.sql', $tablesDefinitions, FILE_APPEND);
  55.  
  56. if(strpos($tables[$i]['Name'], 'backup') === false)
  57. {
  58. $stmt = $this->db->query('SELECT * FROM `'.$tables[$i]['Name'].'`');
  59. $this->array1 = array();
  60. $this->array2 = array();
  61. $rows = 0;
  62. $cut = 5000;
  63.  
  64. while($row = $stmt->fetch(\PDO::FETCH_ASSOC))
  65. {
  66. foreach($row as $key => $val)
  67. $this->array1[] = str_replace('\'', '\'\'', $val);
  68.  
  69. $this->array2[] = '(\''.implode('\', \'', $row).'\')';
  70. $this->array1 = array();
  71. $rows++;
  72.  
  73. if($rows == $cut)
  74. {
  75. if($this->array2 !== array())
  76. file_put_contents(BASEPATH.'/Cache/dump.sql', 'INSERT INTO `'.$tables[$i]['Name'].'` VALUES '."\r\n ".implode(', ', $this->array2).";\r\n\r\n\r\n", FILE_APPEND);
  77.  
  78. unset($this->array2);
  79.  
  80. $this->array2 = array();
  81. $rows = 0;
  82. }
  83. }
  84.  
  85. if($valuesArray2 !== array())
  86. file_put_contents(BASEPATH.'/Cache/dump.sql', 'INSERT INTO `'.$tables[$i]['Name'].'` VALUES '."\r\n ".implode(', ', $this->array2).";\r\n\r\n\r\n", FILE_APPEND);
  87.  
  88. $this->array1 = array();
  89. $this->array2 = array();
  90. }
  91.  
  92. echo memory_get_peak_usage(true).' - '.number_format(microtime(true) - START_TIME, 4).'<br />';
  93. }
nospor
1) Przy drugim nie robisz closeCursor

2) Nie buforuj wyników. Ustaw parametr PDO::MYSQL_ATTR_USE_BUFFERED_QUERY na false
adbacz
Dzięki Ci wielkie @nospor. Zmiana buforowania rzeczywiście dała rezultat.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.