У меня периодически возникают проблемы с подключением к ведомому устройству базы данных с помощью InnoDB. Время от времени у меня соединение занимает более 2 секунд. Эти серверы размещены на Amazon EC2.
Сервер приложений - PHP 5.2 / Apache, работающий на Ubuntu. Подчиненное устройство БД работает под управлением Percona XtraDB 5.1 на Ubuntu 9.10. Для хранения данных используется массив EBS Raid.
Мы уже используем разрешение пропуска имени и привязку к адресу 0.0.0.0.
Это заглушка кода PHP, которая не работает.
$tmp = mysqli_init(); $start_time = microtime(true); $tmp->options(MYSQLI_OPT_CONNECT_TIMEOUT, 2); $tmp->real_connect($DB_SERVERS[$server]['server'], $DB_SERVERS[$server]['username'], $DB_SERVERS[$server]['password'], $DB_SERVERS[$server]['schema'], $DB_SERVERS[$server]['port']); if(mysqli_connect_errno()){ $timer = microtime(true) - $start_time; mail($errors_to,'DB connection error',$timer); }
На сервере БД доступно более 300 МБ для новых подключений, а размер сервера далек от максимально допустимого (60 из 1200). Загрузка на обоих серверах <2 на 4 основных экземплярах m1.xlarge.
Некоторые особенности конфигурации mysql
max_connections = 1200 thread_stack = 512K thread_cache_size = 1024 thread_concurrency = 16 innodb-file-per-table innodb_additional_mem_pool_size = 16M innodb_buffer_pool_size = 13G
Любая помощь в отслеживании источника замедления приветствуется.
[РЕДАКТИРОВАТЬ] Я обновляю значения sysctl для сети, но, похоже, они не решают проблему. Я внес следующие изменения как в базу данных, так и на сервер приложений.
net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_sack = 0 net.ipv4.tcp_timestamps = 0 net.ipv4.tcp_fin_timeout = 20 net.ipv4.tcp_keepalive_time = 180 net.ipv4.tcp_max_syn_backlog = 1280 net.ipv4.tcp_synack_retries = 1 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 87380 16777216
[РЕДАКТИРОВАТЬ] По предложению jaimieb, я добавил трассировку и записал следующие данные, используя время. Этот сервер обрабатывает около 51 запроса в секунду в это время суток. Ошибка подключения возникла один раз (в 13:06:36) в течение 3-минутного окна, описанного ниже. Поскольку произошел 1 сбой и около 9 200 успешных подключений, я думаю, что это не даст ничего значимого с точки зрения отчетности.
Сценарий:
date >> /root/database_server.txt (time mysql -h database_Server -D schema_name -u appuser -p apppassword -e '') > /dev/null 2>> /root/database_server.txt
Полученные результаты:
=== Application Server 1 === Mon Feb 22 13:05:01 EST 2010 real 0m0.008s user 0m0.001s sys 0m0.000s Mon Feb 22 13:06:01 EST 2010 real 0m0.007s user 0m0.002s sys 0m0.000s Mon Feb 22 13:07:01 EST 2010 real 0m0.008s user 0m0.000s sys 0m0.001s === Application Server 2 === Mon Feb 22 13:05:01 EST 2010 real 0m0.009s user 0m0.000s sys 0m0.002s Mon Feb 22 13:06:01 EST 2010 real 0m0.009s user 0m0.001s sys 0m0.003s Mon Feb 22 13:07:01 EST 2010 real 0m0.008s user 0m0.000s sys 0m0.001s === Database Server === Mon Feb 22 13:05:01 EST 2010 real 0m0.016s user 0m0.000s sys 0m0.010s Mon Feb 22 13:06:01 EST 2010 real 0m0.006s user 0m0.010s sys 0m0.000s Mon Feb 22 13:07:01 EST 2010 real 0m0.016s user 0m0.000s sys 0m0.010s
[РЕДАКТИРОВАТЬ] В соответствии с предложением, полученным по вопросу LinkedIn, я попытался установить значение back_log выше. Мы использовали значение по умолчанию (50) и увеличили его до 150. Мы также увеличили значение ядра / proc / sys / net / core / somaxconn (максимальное количество подключений к сокетам) до 256 как на сервере приложения, так и на сервере базы данных с 128 по умолчанию. В результате мы наблюдали некоторое повышение загрузки процессора, но по-прежнему получали таймауты подключения.
Насколько хорошо это работает, если исключить PHP из уравнения? Используйте клиент CLI mysql для подключения к серверу. Попробуйте его как с самого сервера db, так и с сервера приложений:
time mysql -h localhost -D dbname -u username -ppassword -e ''
Проверьте свои DNS-серверы, я думаю, что mysql может пытаться разрешить обратный DNS подключенного хоста. Также убедитесь, что / etc / hosts в порядке и имеет "127.0.0.1 localhost"
Это может быть даже не близко, но не могли бы вы ждать сброса на диск? Может тайм-аут?
Учтите, что в случае сбоя вы можете потерять до 1 минуты данных.
innodb_flush_log_at_trx_commit = 0 (по умолчанию 1)
Это приведет к тому, что InnoDB будет записывать и очищать буфер журнала только один раз в секунду. : http://dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit