2013-02-28 3 views
11

Tło: pobrałem * .sql zapasową bazy mojego witryna oparta na WordPressie, a zastąpić wszystkie wystąpienia starej tabeli bazy danych prefiksu na nowy (na przykład z domyślnego wp_ do czegoś podobnego asdfghjkl_).Naprawiono zepsute dane z powodu edytowania bazy danych MySQL w edytorze tekstu?

Właśnie dowiedziałem się, że WordPress używa serializowanych ciągów PHP w bazie danych, a to, co zrobiłem, będzie pogwałcone integralności serializowanych długości znaków.

Chodzi o to, że usunąłem plik kopii zapasowej tuż przed tym, jak dowiedziałem się o tym (ponieważ moja strona wciąż działała dobrze) i od tego czasu zainstalowałem wiele wtyczek. Tak więc, nie ma to sposób mogę powrócić, i dlatego chcieliby wiedzieć dwie rzeczy:

  1. Jak mogę rozwiązać ten problem, jeśli w ogóle możliwe?

  2. Jakie problemy mogą to spowodować?

(This article stwierdza, że ​​WordPress blog na przykład, może stracić swoje ustawienia i widgety. Ale to nie wydaje się, że się ze mną stało, ponieważ wszystkie ustawienia dla mojego blogu są nienaruszone. Ale mam bez pojęcia, co mogło zostać złamane w środku, lub co wydaje że to stwarzać w przyszłości stąd to pytanie)

Odpowiedz

11

Odwiedź tę stronę.. http://unserialize.onlinephpfunctions.com/

na tej stronie powinieneś zobaczyć próbkę odcinkach ciąg: a:1:{s:4:"Test";s:17:"unserialize here!";}. Weź kawałek tego - s:4:"Test";. Oznacza to "ciąg", 4 znaki, a następnie rzeczywisty ciąg znaków. Jestem prawie pewien, że to, co zrobiłeś, spowodowało, że liczba znaków numerycznych nie jest zsynchronizowana z ciągiem znaków. Zagraj za pomocą narzędzia na stronie wspomnianej powyżej, a zobaczysz, że pojawi się błąd, jeśli na przykład zmienisz "Test" na "Tes".

To, co musisz zrobić, powoduje, że liczba znaków pasuje do nowego ciągu. Jeśli nie uszkodziłeś żadnego z innych kodowań - usunięto dwukropek lub coś takiego - to powinno naprawić problem.

+0

Dziękuję bardzo. Twoja odpowiedź mi pomogła. @ s_ha_dum –

+0

Dzięki za wyjaśnienie! Po znalezieniu problemów znalazłem ten kod, aby ponownie poprawić serializacje. Sprawdź https://stackoverflow.com/a/38890855/2323296 –

7

doszedłem do tego samego problemu po próbuje zmienić domenę z localhost do rzeczywistego adresu URL. Po poszukiwaniach znalazłem odpowiedź w dokumentacji WordPress:

https://codex.wordpress.org/Moving_WordPress

będę cytować co jest tam napisane:

Aby uniknąć tego problemu serializacji, masz trzy opcje:

  • Jeśli chcesz> uzyskać dostęp do pulpitu nawigacyjnego, użyj wtyczek Update Betting Velvet Blues Update.
  • Użyj polecenia WP-CLI do wyszukiwania-zamień, jeśli Twój dostawca usług hostingowych (lub Ty) zainstalował WP-CLI.
  • Przeprowadź wyszukiwanie i zamień zapytanie ręcznie w bazie danych.Uwaga: Wykonuj wyszukiwanie i zastępuj tylko w tabeli wp_posts.

skończyło się używając WP-CLI, który jest w stanie zastąpić rzeczy w bazie danych bez przerywania serializacji: http://wp-cli.org/commands/search-replace/

+0

Dziękuję. Nie wiem, dlaczego nie zwróciło to większej uwagi. Miał ten sam problem, a także zakończył korzystanie z 'WP-CLI'. Jest to najłatwiejszy sposób na zrobienie tego, jeśli chcesz zmienić wygląd. –

1

Jeśli błąd jest ze względu na długość struny niepoprawność (coś mam postrzegane często), to powinieneś być w stanie dostosować ten skrypt, aby je naprawić:

foreach($strings as $key => $str) 
{ 
    try { 
     unserialize($str); 
    } catch(exception $e) { 
     preg_match_all('#s:([0-9]+):"([^;]+)"#',$str,$m); 
     foreach($m[1] as $k => $len) { 
      if($len != strlen($m[2][$k])) { 
       $newstr='s:'.strlen($m[2][$k]).':"'.$m[2][$k].'"'; 
       echo "len mismatch: {$m[0][$k]}\n"; 
       echo "should be: $newstr\n\n"; 
       $strings[$key] = str_replace($m[0][$k], $newstr, $str); 
      } 
     } 
    } 
} 
2

wiem, jest to stara sprawa, ale lepiej późno niż wcale, jak sądzę. Niedawno pojawił się ten problem, po odziedziczeniu bazy danych, która miała znaleźć/zamień wykonane w serializowanych danych. Po wielu godzinach poszukiwań odkryłem, że dzieje się tak dlatego, że liczby łańcuchów były wyłączone. Niestety, było tak dużo danych z dużą ilością ucieczek i nowych linii i nie wiedziałem, jak liczyć w niektórych przypadkach i miałem tak dużo danych, że potrzebowałem czegoś zautomatyzowanego.

Po drodze natknąłem się na to pytanie, a post Benubird pomógł mi postawić właściwą drogę. Jego przykładowy kod nie działał w produkcji na złożonych danych, zawierających liczne znaki specjalne i HTML, z bardzo głębokimi poziomami zagnieżdżania, i nie obsługiwał poprawnie niektórych znaków i znaków kodowanych. Więc trochę zmodyfikowałem i spędziłem niezliczone godziny, pracując nad dodatkowymi błędami, aby moja wersja mogła "naprawić" zserializowane dane.

// do some DB query here 
while($res = db_fetch($qry)){ 
    $str = $res->data; 
    $sCount=1; // don't try to count manually, which can be inaccurate; let serialize do its thing 
    $newstring = unserialize($str); 
    if(!$newstring) { 
     preg_match_all('/s:([0-9]+):"(.*?)"(?=;)/su',$str,$m); 
#   preg_match_all("/s:([0-9]+):(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")(?=;)/u",$str,$m); // alternate: almost works but leave quotes in $m[2] output 
#   print_r($m); exit; 
     foreach($m[1] as $k => $len) { 
      /*** Possibly specific to my case: Spyropress Builder in WordPress ***/ 
      $m_clean = str_replace('\"','"',$m[2][$k]); // convert escaped double quotes so that HTML will render properly 
      // if newline is present, it will output directly in the HTML 
      // nl2br won't work here (must find literally; not with double quotes!) 
      $m_clean = str_replace('\n', '<br />', $m_clean); 
      $m_clean = nl2br($m_clean); // but we DO need to convert actual newlines also 
      /*********************************************************************/ 
      if($sCount){ 
       $m_new = $m[0][$k].';'; // we must account for the missing semi-colon not captured in regex! 
       // NOTE: If we don't flush the buffers, things like <img src="http://whatever" can be replaced with <img src="//whatever" and break the serialize count!!!     
       ob_end_flush(); // not sure why this is necessary but cost me 5 hours!! 
       $m_ser = serialize($m_clean); 
       if($m_new != $m_ser) { 
        print "Replacing: $m_new\n"; 
        print "With: $m_ser\n"; 
        $str = str_replace($m_new, $m_ser, $str); 
       } 
      } 
      else{ 
       $m_len = (strlen($m[2][$k]) - substr_count($m[2][$k],'\n')); 
       if($len != $m_len) { 
        $newstr='s:'.$m_len.':"'.$m[2][$k].'"'; 
        echo "Replacing: {$m[0][$k]}\n"; 
        echo "With: $newstr\n\n"; 
        $str = str_replace($m_new, $newstr, $str); 
       } 
      } 
     } 
     print_r($str); // this is your FIXED serialized data!! Yay! 
    } 
} 

Trochę naukowy wyjaśnienie moich zmian:

  • Okazało się, że stara się liczyć z kodem Benubird jako baza była zbyt niedokładne dla dużych zbiorów danych, więc skończyło się tylko za pomocą serializacji aby mieć pewność, liczba była dokładna.
  • Uniknęłem try/catch, ponieważ w moim przypadku próba się powiodła, ale właśnie zwrócił pusty ciąg znaków. Dlatego zamiast tego sprawdzam puste dane.
  • Próbowałem wielu regex, ale tylko mod na Benubird's będzie dokładnie obsługiwać wszystkie przypadki. W szczególności musiałem zmodyfikować część, która została sprawdzona dla ";" ponieważ pasowałoby do CSS, takich jak "width: 100%; height: 25px;" i zepsuł wynik. Więc użyłem pozytywnego uprzedzenia, aby dopasować tylko, gdy ";" był poza zbiorem podwójnych cytatów.
  • Moja sprawa zawierała mnóstwo nowych linii, HTML i Escaped podwójnych cytatów, więc musiałem dodać blok, żeby to wyczyścić.
  • Było kilka dziwnych sytuacji, w których dane zostałyby niepoprawnie zastąpione przez wyrażenie regularne, a następnie serializacja również zliczyłaby to niepoprawnie. Znalazłem NIC na jakichkolwiek stronach, aby pomóc z tym i na końcu pomyślałem, że może to być związane z buforowaniem lub czymś podobnym i wypróbowane przepłukanie bufora wyjściowego (ob_end_flush()), który działał, dzięki Bogu!

Mam nadzieję, że to pomoże komuś ... Zajęło mi to prawie 20 godzin, włączając w to badania i zajmowanie się dziwnymi sprawami! :)

+0

Czy możesz wykonać plik wykonywalny dla systemu Windows, który ma opcję wyszukiwania i zamiany łańcucha znaków w pliku SQL? Lub przynajmniej plik PHP, w którym można określić plik źródłowy, plik docelowy, ciąg wyszukiwania i zastąp ciąg. –

1

Osobiście nie lubię pracy w PHP lub umieszczania moich danych uwierzytelniających w publicznym pliku. Stworzyłem skrypt ruby ​​naprawić serializations które można uruchomić lokalnie:

https://github.com/wsizoo/wordpress-fix-serialization

kontekstowe Edit: podszedłem mocowania serializacji najpierw identyfikacji serializacji poprzez regex, a następnie ponowne przeliczenie wielkości bajtów zamkniętego łańcucha danych.

$content_to_fix.gsub!(/s:([0-9]+):\"((.|\n)*?)\";/) {"s:#{$2.bytesize}:\"#{$2}\";"} 

Następnie aktualizuję określone dane za pomocą kwerendy zaktualizowanej z zapytaniem sql.

escaped_fix_content = client.escape($fixed_content) 

query = client.query("UPDATE #{$table} SET #{$column} = '#{escaped_fix_content}' WHERE #{$column_identifier} LIKE '#{$column_identifier_value}'") 
+1

Czy możesz podsumować podejście i zamieścić tutaj część kodu? Linki nie są odpowiedzią same, mogą się zepsuć lub usunąć ich zawartość. – brichins

+0

Dzięki @brichins! Wciąż nowe w tym ... edytowane w celu zapewnienia kontekstu. – wsizoo

1

Ten skrypt (https://interconnectit.com/products/search-and-replace-for-wordpress-databases/) może przyczynić się do aktualizowania bazy danych SQL z odpowiednich adresów URL na całym świecie, nie napotykając odcinkach problemy z danymi, ponieważ będzie aktualizować „znaków liczyć”, które mogłyby rzucić się używać zsynchronizowany ilekroć odcinkach dane występuje.

Kroki byłoby:

  1. jeśli już importowane zawiedli bazy danych (widgety nie pracy, możliwości rozrywki nie ma, itp), tylko kropla tej bazy użyciu PhpMyAdmin. To znaczy, usuń wszystko. Następnie wyeksportuj i pod ręką niezrealizowany zrzut starej bazy danych.

  2. Teraz musisz zaimportować (niezaktualizowaną) starą bazę danych do nowo utworzonej bazy danych . Możesz to zrobić poprzez importowanie lub kopiowanie ponad db z PhpMyAdmin. Zauważ, że do tej pory nie wykonaliśmy jeszcze żadnego wyszukiwania ani zamiany; mamy tylko starą zawartość bazy danych i strukturę do nowej bazy danych z własnym użytkownikiem i hasłem. Twoja strona będzie prawdopodobnie niedostępna w tym momencie.

  3. Upewnij się, że pliki WordPress zostały świeżo przesłane do właściwego folderu na serwerze i edytuj plik wp-config.php, aby połączyć go z nową bazą danych.
  4. Prześlij skrypt do folderu "tajnego" - tylko z powodów bezpieczeństwa - na tym samym poziomie, co wp-admin, wp-content i wp-includes. Nie zapomnij usunąć go, gdy tylko nastąpiło wyszukiwanie i zastąpienie , ponieważ istnieje ryzyko udostępnienia danych DB dla całego Internetu.
  5. Teraz skieruj przeglądarkę do tajnego folderu i użyj dobrze funkcjonującego interfejsu skryptu . To bardzo oczywiste. Po użyciu przejdź do całkowicie usunąć go z serwera.

To powinno mieć poprawną aktualizację bazy danych, bez problemów z serializowanymi danymi: nowy adres URL zostanie ustawiony wszędzie, a liczba seryjna znaków danych zostanie odpowiednio zaktualizowana.

Widżety zostaną przekazane, a ustawienia kompozycji - dwa z typowych miejsc korzystających z serializowanych danych w WordPress.

Gotowe i przetestowane rozwiązanie!

Powiązane problemy