Столкнулся с багой оригинального характера. Когда написал свою первую прокладку под mysq...
Столкнулся с багой оригинального характера. Когда написал свою первую прокладку под mysql
сильно радовался тому, что все работает и довольно привычно-удобно. Но оказывается я страшный лошара. В этой самой прокладке есть метод
foundRows который должен возвращать (и это иногда работает!) количество рядов в запросе без учета LIMIT (см.
FOUND_ROWS()). Загвоздка в том что FOUND_ROWS() сработает только для того запроса который был перед ним в пределах одного коннекта. То есть сначала запрос на select с лимитом и следующим обязательно должен быть select found_rows() примерно так
SELECT SQL_CALC_FOUND_ROWS *
FROM tbl_name
WHERE id > 100
LIMIT 10;
SELECT FOUND_ROWS();
В ситуации с асинхронными запросами, когда используется только один коннект, при приличной паралельной загрузке между этими двумя запросами вполне может проскочить другой запрос и FOUND_ROWS() начнет "врать". По сути очередь будет выглядеть так
SELECT SQL_CALC_FOUND_ROWS *
FROM tbl_name
WHERE id > 100
LIMIT 10;
# пример "проскочившего" запроса
SELECT *
FROM tbl_name_2
WHERE id=12;
SELECT FOUND_ROWS();
И вот уже FOUND_ROWS() возвращает совершенно не то что нужно. Для создания тестовой загрузки проекта можно пользоваться
Apache ab например вот так
# 900 раз запросить страницу с 10 конкурентными запросами
ab -c 10 -n 900 http://cocainum.info/post/301/
В моей ситуации во время такого тестирования мелкие запросы как раз влезали между запросами с лимитом и запросами подсчета рядов. В результате пейджинг думал что страниц у него ровно одна штука и исчезал со всех своих страниц как класс, пока шла нагрузка с конкурентными запросами.
А теперь внимание вопрос для третьего класса средней школлы..
Как поделить три яблока на четверых чтобы каждый получил по яблоку и никто не получил по лицу. Как же это решить? Я не нашел удобного толкового решения. Callback hell забарывает и на код становится жутко глядеть. Решение есть, смотрим тут
Pooling connections. То есть если необходимо по каким-то причинам строго последовательно выполнять запросы, то из пула специально берем отдельный коннект и пользуемся им. Выглядеть это будет примерно так:
pool.getConnection(function(err, conn) {
conn.query( 'SELECT SQL_CALC_FOUND_ROWS * FROM tab1 LIMIT 100,10', function(err, rows) {
conn.query('SELECT FOUND_ROWS() as cnt', function(err, rows){
// получаем общее кол-во строк
// ...
// освобождаем соединение
conn.release();
});
});
});
В прокладке я это реализовал, но пока что выглядит все это жутко, надо либо свыкнуться с этой мыслью, либо придумать что-то лучше. Пока переделанную версию выкладывать смысла нет по-моему.
Стоит обратить внимание на секцию настроек
"Pool options" хотя бы чтобы научиться регулировать количество соединений
connectionLimit.
Вообще доделать конечно надо ради интереса, но по-хорошему надо переезжать уже на
Sequelize или что-то такое.