Pierwszym z tematów jest reprezentacja czasu w bazach danych oraz w skrypcie. MySQL udostępnia formaty DATE oraz TIME, a dzięki odpowiednim funkcjom można łatwo wyciągnąć z nich np. informację o miesiącu, pozostawiając wszystkie inne. Dla potrzeb przetwarzania przez skrypt oraz szybkiej arytmetyki stosuje się jednak zazwyczaj uniksowe znaczniki czasu, czyli zwyczajne liczby określające ilość sekund, jakie upłynęły od 1 stycznia 1970 roku. W bazie danych można je składować w zwyczajnym polu INT ze znakiem, gdzie liczby ujemne to liczba sekund, jakie pozostały do wymienionej wyżej daty. Każdy informatyk szybko sobie przeliczy, że za pomocą 32-bitowego pola można reprezentować ok. 4 miliardów różnych liczb. Nałożywszy ten zakres na oś czasu wychodzi, że najwcześniejsza dająca się zapisać tak data to 13 grudnia 1901 roku, zaś najpóźniejsza - 19 stycznia 2038 roku. Jeśli licznik zegaru dojdzie do tej daty, zgodnie z zasadą działania komputerowej arytmetyki, zostanie on zawinięty do przeszłości, dokładnie tak samo, jak to miało miejsce ze słynnym niewypałem pt. problem roku 2000.
Aktualnie proponuje się dwa rozwiązania problemu roku 2038: pierwsze z nich polega na zmianie formatu znacznika czasu na liczbę 32-bitową, ale bez znaku, dzięki czemu zakres wydłuży się do okolic roku 2100. Drugie z rozwiązań jest znacznie drastyczniejsze; polega na przejściu na czas 64-bitowy. Obsłuży on ponad 290 miliardów lat, czyli nowy zakres będzie znacznie większy, niż dotychczasowy wiek wszechświata. Jeśli chodzi o skrypty, ich aktualizacja nie jest zbyt kłopotliwa. Wystarczy wydłużyć wszystkie pola przechowujące datę z INT do BIGINT; cała reszta zależy już od admina, a konkretniej użytej wersji interpretera oraz systemu operacyjnego. W FreeBSD typ time_t w języku C odpowiedzialny za timestamp został już wydłużony do 64 bitów, lecz w Linuksie dalej jest ono dwukrotnie krótsze. Ponadto niezbędna może okazać się aktualizacja interpretera - dla PHP będzie to przynajmniej wersja 6, ponieważ dopiero tam pojawia się obsługa 64-bitowych liczb. Przebudowa oprogramowania nie jest taką pilną sprawą; jeśli faktycznie mamy zamiar pisać teraz skrypt/bazę danych, która ma chodzić przez 30 lat, możemy zawczasu podjąć środki zaradcze; w przeciwnym wypadku należy być jedynie świadomym, że 32-bitowy INT nie jest wieczny.
Kolejny stosunkowo nowy wynalazek to IPv6, który wydatnie rozszerza pulę dostępnych adresów IP tak, że na jednego mieszkańca Ziemi przypada ich ok. 5*10^28. W skryptach PHP adresy IP wykorzystuje się do kontroli sesji lub notowania np. przy komentarzach, lecz większość z nich używa do tego celu wyłącznie 32-bitowych pól, przez co będą one nieprawidłowo pracować w sieciach IPv6. Perspektywa przesiadki na takowe jest znacznie bliższa w czasie, niż problemy dat. Szacuje się, że pula adresów IPv4 wyczerpie się ok. 2011 roku, zaś rządy niektórych krajów wydały już zarządzenia w celu przebudowy swej infrastruktury. Administracja USA ma czas do końca 2008 roku na przejście na nowy protokół, zaś Chińczycy wdrażają projekt China Next Generation Internet. Niektórym krajom przydzielono już także rekordy DNS typu AAAA (IPv6) dla ich narodowych domen najwyższego poziomu. Tyle tytułem wprowadzenia, przejdźmy do implementacji w skryptach i bazach danych. Jest to nieco skomplikowane, ponieważ ciężko znaleźć odpowiedni typ danych do składowania. MySQL-owe liczby kończą się na 64 bitach i jedynym rozsądnym rozwiązaniem jest typ CHAR(16) (128 bitów = 16 bajtów). W analogiczny sposób adres zapiszemy w PHP, jednak tu musimy też zwrócić uwagę na problem z jego translacją do czytelnej postaci. PHP posiada funkcje inet_ntop() oraz inet_pton(), które obsługują zarówno IPv4, jak i IPv6, lecz nie są one dostępne na platformie Windows, gdy tymczasem duża grupa programistów pisze skrypty właśnie w tym systemie. W komentarzach do dokumentacji PHP można znaleźć skryptowe implementacje obu funkcji, które można użyć w takiej sytuacji.
Nawet jeśli aktualnie korzystamy z IPv4, przejście na IPv6 może oszczędzić nam kłopotów w przyszłości. Nowy protokół przewiduje specjalną klasę: ::ffff:0:0/96, którą można wykorzystać do zapisywania adresów IPv4 w strukturze IPv6 (zamrożone pierwsze 96 bitów, z czego 80 ustawione jest na 0, a 16 na 1, natomiast dalej idą 32 bity adresu IPv4). Odpowiednio zaprojektowana już teraz aplikacja będzie mogła dzięki temu niemal transparentnie przejść na IPv6.
Ostatnie rozwiązanie, jakie zamierzam zaimplementować, to obsługa replikacji serwerów MySQL. Technologia ta pojawiła się w MySQL-u 3.23 i umożliwia rozładowanie obciążenia. Mamy tutaj wyróżnionych n maszyn, z którymi możemy nawiązać połączenie do odczytu danych oraz jeden wyróżniony serwer prowadzący dziennik zmian. Modyfikacja danych możliwa jest wyłącznie za jego pośrednictwem. Wysyłając do niego np. zapytanie UPDATE, jego wyniki zostaną rozpropagowane między wszystkie pozostałe serwery, dzięki czemu dane pozostaną zsynchronizowane. W takim środowisku skrypt musi utrzymywać dwa połączenia z bazą danych: jedno do odczytu i drugie do zapisu, przy czym pierwsze jest nawiązywane np. z losowym dostępnym serwerem. Bardziej wymagające serwisy wymagają obecności klastra MySQL, gdzie do każdej z maszyn posiadamy możliwość odczytu i zapisu. Dość prosto jest tak napisać skrypt, aby mógł pracować bezproblemowo z każdą konfiguracją. Moja implementacja przewiduje udostępnienie skryptowi dwóch zmiennych obiektowych: $sqr oraz $sqw. Są one wypełniane następująco:
- Dla połączeń z pojedynczym serwerem: odczytujemy z konfiguracji adres serwera, nawiązujemy z nim jedno połączenie i obiekt PDO wprowadzamy do obu tych zmiennych.
- Dla serwerów z replikacją: skrypt tworzy dwa obiekty PDO wprowadzane do każdej ze zmiennych. Jeden zostaje nakierowany na serwer główny obsługujący zapis, natomiast drugi na losowo wybraną z pozostałych maszyn.
- Dla klastrów: skrypt tworzy jeden obiekt PDO, wprowadza go do obu zmiennych, przy czym adres serwera wybierany jest losowo z dostępnej puli.
Dodatkowo stosuję nakładkę Open Power Driver z opcją "leniwej ewaluacji", czyli nawiązywania połączenia dopiero wtedy, gdy faktycznie jest ono niezbędne. Jeśli teraz wszystkie zapytania SELECT będziemy obsługiwać poprzez zmienną $sqr, a INSERT/UPDATE/DELETE poprzez $sqw, ten sam kod będzie działać bez przeszkód w każdej sytuacji. Tyle teoria, a jak wyjdzie w praktyce, to zobaczymy. Aktualnie kończę instalowanie systemu na drugim komputerze, aby móc skonfigurować poprawnie MySQL-a do pracy.















Napisał Loonatic w czwartek, 4 października 2007 o 17:07
"dla PHP będzie to przynajmniej wersja 6, ponieważ dopiero tam pojawia się obsługa 32-bitowych liczb."
Chyba chodziło o liczby 64 bitowe?