Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][MYSQL] Migracja, przenoszenie dużej bazy danych (o. 100MB), Serwer umiera, za dużo za duże INSERTy...
Shinu
post 11.07.2008, 07:27:33
Post #1





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 21.06.2007

Ostrzeżenie: (0%)
-----


Witam,
muszę dokonać migracji: stary niewydajny skrypt forum -> nowy wydajny skrypt forum. Baza ma około 100MB.
Struktura skryptów jest nieco inna, muszę więc przetwarzać dane z pierwszego skryptu, aby je móc wrzucić do drugiego.
I tu mam mały problem, przy próbie parsowania i importu prawie 200k postów "MySQL server has gone away"...

To co udało mi się wykombinować to:
- select w pętli po 5000 rekordów
- jeden insert dodający na raz te 5k rekordów

LOW_PRIORITY nic nie dało,
sleep(5) - prawie nic nie dało (po padzie serwera, daję mysql_close(); sleep(5); ponownie łączę i ponawiam inserta

Pytanie, jak to zrobić by serwer nie umierał?

Skrypt działa w PHP5, baza to MYSQL5

Co ciekawe na początku udaje się dodać kilkadziesiąt tysięcy rekordów (kilka obrotów pętli po 5k), później serwer zdycha już po 5k...

Nie wiem, co jeszcze mogę napisać, co by pomogło w wyjaśnieniu mojego problemu.

Sama pętla mająca za zadanie sparsować i przenieść 200k postów:
Kod
for($ll = 1; $ll <= 39; ++$ll) { // 39*5000 = 195k (to nieco wiecej niz wszystkich postow w bazie)
    $query = 'SELECT f.id, u.uzytkownik, f.id_usera, f.ip, u.email, f.tresc, f.data, f.data_modyfikacji, f.zmodyfikowal, id_watku FROM `forum` f LEFT JOIN `userzy` u ON u.id = f.id_usera ORDER BY f.id ASC';
    $query .= ' LIMIT '. (($ll-1)*5000) . ',' . 5000;

    $resa = mysql_query($query,$ansi);
    if(!$resa) {
        echo '<br>ll= ',$ll,' ansi padło= ', mysql_error($ansi) ,'<br>q= ',$query;

        mysql_close($ansi);
        // wskrzeszamy ANSI
        $host = 'x';
        $db = 'x';
        $user = 'x';
        $pass = 'x';

        $ansi = mysql_connect($host, $user, $pass);
        if($ansi) { echo '<br>Połączenie z ansi...<br>'; }
        else { echo 'nie wskrzeszono :/'; exit(); }
        mysql_select_db($db,$ansi);
        mysql_query("SET NAMES 'latin2'",$ansi);

        $resa = mysql_query($query,$ansi);
        if(!$resa) {
            echo '<br>ll= ',$ll,' ansi padło po wskrzeszeniu :/= ', mysql_error($ansi) ,'<br>q= ',$query;
            break;
        }
    }

    $symbol = array('~','#','@');
    $encje = array('"','>','<','–','“','”','„', '‘', '’','…','[cytuj=~','[cytuj=#','[cytuj=@','[/cytuj]');
    $znaki = array('"',     '>',   '<',   '-',      '"',      '"',      '"',       '\'',      '\'',     '...',    '[quote=', '[quote=', '[quote=', '[/quote]');
    $ii=0;
    $adds=0;
    $query = null;
    while($row = mysql_fetch_assoc($resa)) {

        // konwertujemy i wywalamy encje
        $row['tresc'] = str_replace($encje,$znaki,iconv("latin2", "UTF-8",$row['tresc']));
        // przerabiamy łącza do postów
        $row['tresc'] = preg_replace('|(watek\.php\?WT)=(\d+)#(\d+)([^]]*)]|i','viewtopic.php?pid=$3#$3]',$row['tresc']);
        // przerabiamy łącza do tematów
        $row['tresc'] = preg_replace('|(watek\.php\?WT)=(\d+)([^]]*)]|i','viewtopic.php?id=$2]',$row['tresc']);

        if(!$ii) {
            $query = "INSERT INTO `fbb_posts` (`id`, `poster`, `poster_id`, `poster_ip`, `message`, `posted`, `edited`, `edited_by`, `topic_id`)
        VALUES ";
        }
        $query .=  "(
        '". $row['id'] ."',
        '". iconv("latin2", "UTF-8",$row['uzytkownik']) ."',
        '". ($row['id_usera']==1?'9':$row['id_usera']) ."',
        '". $row['ip'] ."',
        '". mysql_real_escape_string($row['tresc'],$flux) ."',
        '". strtotime($row['data']) ."',
        ". ( strtotime($row['data_modyfikacji'])==0?'NULL': "'".strtotime($row['data_modyfikacji'])."'" ) .",
        ". ( $row['zmodyfikowal']==''?'NULL': "'".str_replace($symbol,'',iconv("latin2", "UTF-8",$row['zmodyfikowal']))."'" ) .",
        '". $row['id_watku'] ."'),";

        ++ $ii;
    }
    mysql_free_result($resa);
    $adds=$adds+$ii;

    $query = rtrim($query, ',');

    if($ii>0) {
        $resf = mysql_query($query,$flux);
        if(!$resf) {
            echo '<br>ll= ',$ll,' flux zdechł e= ', mysql_error($flux) ,'<br>'; //q= <div style="width:100%; height:300px; overflow:scroll;">',$query,'</div>';

            mysql_close($ansi);
            sleep(5);

            // połączenie z FluxBB
            $host = 'x;
            $db = 'x';
            $user = 'x';
            $pass = 'x';

            $flux = mysql_connect($host, $user, $pass);
            if($flux) { echo 'Połączenie z flux...<br>'; }
            else { exit(); }
            mysql_select_db($db,$flux);
            mysql_query("SET NAMES 'utf8'",$flux);

            $resf = mysql_query($query,$flux);
            if(!$resf) {
                echo '<br>ll= ',$ll,' flux zdechł po wskrzeszeniu :/= ', mysql_error($flux) ,'<br>'; //q= <div style="width:100%; height:300px; overflow:scroll;">',$query,'</div>';
                break;
            }
        }
    }
}


Ten post edytował Shinu 11.07.2008, 07:29:23
Go to the top of the page
+Quote Post
suchy1
post 18.07.2008, 14:50:50
Post #2





Grupa: Zarejestrowani
Postów: 246
Pomógł: 8
Dołączył: 2.04.2006
Skąd: Gliwice

Ostrzeżenie: (0%)
-----


Cytat(Shinu @ 11.07.2008, 06:27:33 ) *
MySQL server has gone away


Kiedys mialem podobny problem, moze nie staraj sie polepszac kodu php tylko zajmij sie konfiguracją serwera mysql. W pliku mysql.ini zmień wartośc zmiennej "max_allowed_packet " i zapraszam na oficialna strone link
Go to the top of the page
+Quote Post
Shinu
post 18.07.2008, 22:02:55
Post #3





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 21.06.2007

Ostrzeżenie: (0%)
-----


Hmm... dokumentację MYSQL'a przeglądałem... tak czy siak tę bazę w końcu przepchnąłem "z łapy" (ręcznie inkrementowałem licznik pętli po każdym padzie tongue.gif i tak po kilkunastu razach przeszło wszytko).

A tak czy inaczej, da się jakoś 'zakolejkować' zapytania do bazy aby nie zdychała?
Przecież musi być jakiś sposób na przenoszenie takich baz danych.

Ten post edytował Shinu 18.07.2008, 22:05:07
Go to the top of the page
+Quote Post
yalus
post 25.07.2008, 16:19:52
Post #4





Grupa: Zarejestrowani
Postów: 281
Pomógł: 0
Dołączył: 8.07.2005
Skąd: EU

Ostrzeżenie: (0%)
-----


oczywiscie ze jest inny sposob,
robisz kopie calej bazy (backup) do jednego pliku sql,
a pozniej robisz restore na serwerze na ktory chcesz przeniesc baze

moja baza sklada sie z 17 tabel i srednio w kazdej tabeli jest ok 100 tys. rekordow
caly proces migracj z jednego serwera na inny zajmuje mi ok 30-40min.

uzywam do tego narzedzi ze strony mysql - polecam


--------------------
człowiek nie sznurek wszystko wytrzyma
Go to the top of the page
+Quote Post
Shinu
post 25.07.2008, 22:58:58
Post #5





Grupa: Zarejestrowani
Postów: 8
Pomógł: 0
Dołączył: 21.06.2007

Ostrzeżenie: (0%)
-----


Ale nie o to chodziło. Przenieść bazę z serwera na serwer to jak napisałeś nie problem.

Problem jest kiedy masz przenieść dane z jednej bazy do drugiej (o nieco innej strukturze i dodatkowo parsować kilkanaście kolumn przed wykonaniem inserta).

Ten post edytował Shinu 25.07.2008, 23:00:56
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 26.04.2025 - 04:22