Problem z podłączeniem do bazy oraz długie czasy oczekiwania podczas nawiązywania połączenia

0

Cześć.

Mam aplikację w PHP korzystającą z bazy danych MySQL (5.5). Aplikacja obsługuje niemały ruch (konfiguracja Apache + mod_php = mpm_prefork), od kilkuset do kilku tysięcy połączeń na sekundę. Keepalive jest wyłączony ze względu na fakt, że w większości przypadków połączenie nawiązywane jest przez nowego usera i keepalive staje się problematyczny (za dużo czasu musiałby być utrzymywany aby się przydać). Całość wspiera memcached, który skutecznie wspomaga bazę danych.

W sytuacji, gdy ruch jest mały, nie ma żadnego problemu - wszystko śmiga poprawnie. Kłopoty zaczynają się gdy zwiększy się liczba przychodzących połączeń. Kłopoty objawiają się dwojako: albo połączenie do bazy trwa długo, albo połączenie nie następuje i zwracany jest error.

  1. Długi czas połączenia do bazy
    Korzystam z PDO. Linijka, która otwiera połączenie z bazą - ma w sobie jedynie "new PDO(....)" i argumenty będące stałymi - potrafi się wykonywać nawet przez kilka sekund. Im większy ruch, tym dłuższe czasy oczekiwania. Wcześniej używałem połączenia na 127.0.0.1, po poczytaniu przerzuciłem się na unix_socket (rzekomo szybszy, gdyż po 127.0.0.1 leci po TCP co generuje zbędne narzuty - coś takiego, mogłem czegoś nie zrozumieć :P).

  2. Brak połączenia
    W logach pojawia się:

(2002) SQLSTATE[HY000] [2002] Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

Potrafi przez kilka sekund logować po 100 takich wiadomości na sekundę. Błąd pojawia się cyklicznie przy większym obciążeniu, czasem kilka sekund, czasem kilkanaście - zawsze sam mija i wszystko działa dalej poprawnie. Ta sama wiadomość pojawiała się przed zamianą na unix_socket, oczywiście było info o problemie z połączeniem na 127.0.0.1 (4).

W bazie regularnie odpalając "SHOW PROCESSLIST" zazwyczaj widoczne są jakieś pojedyncze procesy, zdarza się jednak, że w ciągu sekundy pojawia się ich i 100 - zostają jednak szybko wykonane i przy następnym wyświetleniu listy procesów znowu jest spokój.

CPU cały czas obciążony jest na poziomie około 25%, choć zdarza się, że pojedyncze rdzenie pracują przez kilka sekund na 100%.

Googlałem długo - wszystkie problemy z Can't connect to... rozwiązywane są poprzez poprawnie usera, hasła czy nadanie odpowiednich uprawnień. Nie trafiłem na problem, gdzie czasem jest can't connect a potem wszystko działa. Zaznaczę, że nie uświadczam błędów jak "too many connections".

Walczyłem zwiększając back_log i open_files, niestety nie pomogło. Czy duża ilość procesów apache'a, gdzie każdy łączy się do memcache'a, może w jakiś sposób "dławić" możliwość nawiązania połączenia z silnikiem bazy danych?

Czy ktoś spotkał się z takim problemem? Ewentualnie macie może sugestie jak próbować go zdebugować i znaleźć dokładną przyczynę tego dziwnego zachowania?

Ps. Tak konkretnie to korzystam z MySQL Cluster (MySQL 5.5 i NDB 7.2.10), ale liczę, że nie będzie to miało większego wpływu na rozwiązanie/debugowanie, gdyż problem jest z podłączeniem do "zwykłej" bazy danych.

0

Tworząc obiekt PDO wywołuję kod:

$settings = array(
			PDO :: MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", 
			PDO :: ATTR_ERRMODE => PDO :: ERRMODE_EXCEPTION,
			PDO :: ATTR_TIMEOUT => 2
		);
$pdoConnect = new PDO($this -> dsn, $this -> username, $this -> password, $settings);

Opisane w poprzednim poście zachowanie dotyczyło ATTR_TIMEOUT = 5. Po zmniejszeniu do 2 sekund zmieniła się treść błędu - już nie jest can't connect lecz:

(2013) SQLSTATE[HY000] [2013] Lost connection to MySQL server at 'waiting for initial communication packet', system error: 95

W google'u póki co trafiam jedynie na problemy z "reading initial communication packet". Wnioskuję, że MySQL z jakiegoś powodu nie może natychmiastowo wysłać tego "packet'a" i dlatego tyle czasu trwa nawiązanie połączenia (po zmniejszeniu ATTR_TIMEOUT do 2 nie ma sytuacji, żeby utworzenie obiektu PDO trwało dłużej niż 2 sekundy, czyli parametr ten działa poprawnie (wcześniej nigdy nie przekroczyło 5 sekund)).

Edit: Wiem, że powinienem edytować tamten post, ale potraktujmy to jako bump, dobrze? :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1