Migracja MySQL → PostgreSQL aplikacji w Symfony 1.1

Jako, że w MySQL nie dzieje się najlepiej postanowiliśmy zmigrować jeden z naszych projektów na Postgresa. Bazuje on na Symfony 1.1, co oznacza starego Propela 1.2.
Samo przestawienie połączenia nie stwarzało większych problemów, wystarczyło w databases.yml i propel.ini przerobić mysql na pgsql:
all:
propel:
class: sfPropelDatabase
param:
persistent: true
phptype: pgsql
…
propel.database = pgsql propel.database.createUrl = pgsql://zdzislaw@localhost/ propel.database.url = pgsql://zdzislaw@localhost/piwo
Przebudowanie modelu, utworzeniu bazy i jej struktury również wykonało się bez problemu, ale to był koniec tego dobrego.
Brak SERIAL
Niestety, propelowy generator skryptu SQL tworzącego schemat bazy nie uraczył nas typem SERIAL przy identyfikatorach, jednakże w samej aplikacji nie stwarza to problemów, ponieważ sekwencje i bez tego są wykorzystywane. Także trzeba po prostu uważać podczas zabawy w CLI Postgresa, gdy mogą one doprowadzić do anomalii z identyfikatorami.
Dane binarne pobierane „ręcznie”
Drobny problem pojawił się w miejscach, gdzie pobieraliśmy dane binarne (BLOB/BYTEA) własnym zapytaniem, omijając wbudowany we framework Active Record. Dane takie trzeba było dodatkowo „od-eskejpować” funkcją stripcslashes.
AKTUALIZACJA: Po aktualizacji projektu do Symfony 1.2 (chociaż tutaj właściwie chodzi o aktualizację Propela do wersji 1.3) okazało się, że żadne stripcslashes nie będzie potrzebne, ponieważ dane binarne (blob) są pobierane jako… stream. Innymi słowy, przy zapytaniach tworzonych samodzielnie, do akcji musiała wkroczyć funkcja stream_get_contents.
GROUP BY
Najwięcej problemów sprawiło grupowanie, ponieważ PostgreSQL ostro trzyma się standardów i wymusza podanie wszystkich używanych kolumn w klauzuli GROUP BY. MySQL natomiast „po cichu” sam sobie je dołączał. Różnicę w zachowaniu prezentuje poniższy (nie mający większego sensu) przykład:
psql=# select sum(id), id from users; ERROR: column "users.id" must appear in the GROUP BY clause or be used in an aggregate function
mysql> select sum(id), id from users; +---------+----+ | sum(id) | id | +---------+----+ | 45 | 1 | +---------+----+
CONCAT
Łącznie ciągów znaków odbywa się całkiem inaczej w MySQL i PgSQL. W tym pierwszym wykonuje się to za pomocą funkcji CONCAT(), natomiast w drugim wykorzystuje się operator ||. Także trzeba było wykonać małą robótkę ręczną.
FORMAT
W naszym kodzie używaliśmy MySQL-owego FORMAT(), aby ograniczyć liczbę cyfr po przecinku, którego w Postgresie nie ma. Można by tutaj użyć funkcji ROUND(), obecnej i tu i tu, jednak zdecydowaliśmy się przenieść rozwiązanie tego problemu do warstwy języka programowania.
LIKE
LIKE w Postgresie, w przeciwieństwie do MySQL, rozróżnia wielkość znaków. Jednak naprawa tej przypadłości sprowadza się jedynie od zamiany LIKE na ILIKE.
Coś dziwnego
Na koniec coś, czego do końca nie udało nam się zrozumieć. Zaraz po przestawieniu konfiguracji na pgsql, strona przestała odpowiadać (a dokładniej odpowiadała, gdy połączenie z bazą przekroczyło czas oczekiwania). Niemniej jednak PostgreSQL sam w sobie działał, jak również możliwe było połączenie z „czystego” PHP. Jedynie aplikacja Symfony dziwnie się zachowywała. W logach pojawiało się następujące stwierdzenie:
Dec 4 11:20:22 myhost httpd: [wrapped: Could not connect [Native Error: pg_pconnect() [function.pg-pconnect]: Unable to connect to PostgreSQL server: server closed the connection unexpectedly This probably means the server terminated abnormally before or while processing the request.] [User Info: host=localhost port=80 dbname='piwo' user='zdzislaw'] [User Info: Array]]
Taka sama sytuacja powtórzyła się na dwóch różnych maszynach (jednak na tym samym systemie operacyjnym). Niezrozumiałe jest to, że w czasie różnych zabaw z konfiguracją wszystko wracało do normy, jednak nie bardzo da się znaleźć konkretną przyczynę. Innymi słowy nie potrafimy zreprodukować tej sytuacji.
Krótkie podsumowanie
Migracja rozwiniętego projektu w Symfony okazała się być stosunkowo mało problematyczna. Kłopotów mogło by być jeszcze mniej, gdyby unikać rozwiązań specyficznych dla danego systemu baz danych. Ale w końcu jak często migruje się z jednej systemu zarządzania bazami danych do innego?
Podobne wpisy:
- Aktualizacja oprogramowania a wydajność
- Symfony: Paginacja przy własnych/nietypowych warunkach SQL
- Logowanie do pliku wszystkich zapytań w PostgreSQL
Autorzy zdjęć: Michiel van Balen




