В качестве предисловия скажу что мне всегда нравился yaml. Так сложилось что я по большей части работаю с Zend Framework Но к сожалению ZF долго не поддерживал yaml. Тогда я добавил простой класс который был оберткой для Symfony компонента sfYaml и начал по-тихоньку использовать yaml в своих проектах.
Наконец-то в ZF 1.11.12 добавил Zend_Config_Writer_Yaml и я решил переконвертировать конфиги из ini в yaml
Недолго думая, я нашел на просторах интернета готовый скрипт. Выглядел примерно так.
$inputfile = APPLICATION_PATH . '/configs/application.ini';
$outputfile = APPLICATION_PATH. '/configs/application.yml';
$config = new Zend_Config_Ini($inputfile, null, array('allowModifications' => false, 'skipExtends'=> true));
$writer = new Zend_Config_Writer_Yaml();
$writer->write($outputfile, $config, true, true);
Такс, используются только ZF классы, никакой самодеятельности — уже хорошо. Попробывал переконвертировать. Получилось все как надо. Запустил тесты — все работает. Хорошо, теперь сделаем тоже самое на боевом сервере.
Через некоторое время мы стали получать ошибку от mysql General error: 1205 Lock wait timeout exceeded; Я пробую выполнить просто запрос и напарываюсь на лок. Хорошо смотрим SHOW PROCESSLIST и ничего не видим. Нужно отметить что пробема касалось только InnoDB таблиц, а 90-95% у нас MyISAM. Погуглил немного по этому поводу — пробуем делать show engine innodb status. Вижу только not started threads т.е. нет транзакции запущенной, которая могла бы лочить другие запросы.
Пробую дернуть админов — ничего ценого от них не узнал. Предложили добавить индексы… ну епрст.
Ладно, надо же что то делать. Мы не так давно начали импользовать Gearman — соответственно есть воркеры, которые по сути являются демонами и открывают долгие коннекты. Начал грешить на них — дай думай перезапущу их. И помогло лок снялся. Но причина то все равно не ясна. Добавил принутильный коммит после выполнения каждой задачи — вроде все тихо.
На следующий день проверяю мыло — такая же история. Периодически прилетают подобные ошибки.
Тут так и хочется спросить, кто уже догадался что произошло?
Менеджеры жалуются что клиент не может обновить инфу. Проверяю — действительно запрос есть а данные не меняются. Тут же вспоминаю про вчерашние COMMIT-ы принудительные. Ну чем черт не шутит, давай попробуем сделать
show variables like “%autocommit%”;
Получаю ON все правильно, тоже самое их php и… барабанная дробь OFF. (до этого момента признаться вспоминал админов всеми нехорошими словами, а оказывается нет виноват сам)
В итоге — все оказалось банально и просто.
Такс… ну и как такое может быть все ведь работало, смотрим в конфиги и обнаруживаем незначительную детальку.
resources.multidb.dbname.adapter = “pdo_mysql”
resources.multidb.dbname.host = “localhost”
resources.multidb.dbname.username = “user”
resources.multidb.dbname.password = “pass”
resources.multidb.dbname.dbname = “dbname”
resources.multidb.dbname.driver_options.1002 = “SET NAMES utf8;”
переконвертировано
resources: multidb: dbname: adapter: pdo_mysql host: localhost username: user password: pass dbname: dbname driver_options: - SET NAMES utf8;
как видите при конвертации 1002 превратилось фактически в 0. Дальше если взглянуть чуть глубже увидим
в Zend_Db
// PDO constant values discovered by this script result:
const ATTR_AUTOCOMMIT = 0;
…
Ну и на последок виновник торжества — Zend_Config_Writer_Yaml
/**
* Service function for encoding YAML
*
* @param int $indent Current indent level
* @param array $data Data to encode
* @return string
*/
protected static function _encodeYaml($indent, $data)
{
reset($data);
$result = "";
$numeric = is_numeric(key($data)); // look here
foreach($data as $key => $value) {
if(is_array($value)) {
$encoded = "n".self::_encodeYaml($indent+1, $value);
} else {
$encoded = (string)$value."n";
}
$result .= str_repeat(" ", $indent).($numeric?"- ":"$key: ").$encoded; // and look here
}
return $result;
}
Напоследок хочу добавить что если использовать SymfonyComponents/YAML/sfYaml.php, о котором я упоминал в начале статьи (я написал для него оч простую обертку для удобного использовая в ZF) и добавить в наш пример
$writer->setYamlEncoder(array(‘App_Yaml’, ‘dump’));
то все переконвертируется правильно.
Так что друзья будьте внимательны когда дело касается конфигов.
Не судите строго — первый пост на хабре.
Автор: wild_honey