manticoresoftware / manticoresearch

Easy to use open source fast database for search | Good alternative to Elasticsearch now | Drop-in replacement for E in the ELK soon
https://manticoresearch.com
GNU General Public License v3.0
9.11k stars 509 forks source link

Регулярный CRASH под FreeBSD #1460

Open LEO111 opened 1 year ago

LEO111 commented 1 year ago

Регулярно падает searchd при различных запросах, при select, при update и replace - никакой четкой связи нет. Запросы приводящие к крашу могут быть к трем разным индексам.

indextool --check ничего подозрительного не выдает.

Собрано всё на FreeBSD 13.2-RELEASE-p3 FreeBSD 13.2-RELEASE-p3 GENERIC amd64

Версия Manticore 6.2.12, собиралась с исходников со стандартными переменными окружения.

В логах следующее:

-------------- backtrace begins here --------------- Program compiled with Clang 14.0.5 Configured with flags: Configured with these definitions: -DDISTR_BUILD= -DUSE_SYSLOG=1 -DWITH_GALERA=1 -DWITH_RE2=1 -DWITH_RE2_FORCE_STATIC=1 -DWITH_STEMMER=1 -DWITH_STEMMER_FORCE_STATIC=1 -DWITH_NLJSON=1 -DWITH_UNIALGO=1 -DWITH_ICU=1 -DWITH_ICU_FORCE_STATIC=0 -DWITH_SSL=1 -DWITH_ZLIB=1 -DWITH_ZSTD=1 -DDL_ZSTD=1 -DZSTD_LIB=libzstd.so.1 -DWITH_CURL=1 -DDL_CURL=1 -DCURL_LIB=libcurl.so.4 -DWITH_ODBC=1 -DDL_ODBC=1 -DODBC_LIB=libodbc.so.2 -DWITH_EXPAT=1 -DDL_EXPAT=1 -DEXPAT_LIB=libexpat.so.1 -DWITH_ICONV=1 -DWITH_MYSQL=1 -DDL_MYSQL=1 -DMYSQL_LIB=libmariadb.so.3 -DWITH_POSTGRESQL=1 -DDL_POSTGRESQL=1 -DPOSTGRESQL_LIB=libpq.so.5 -DLOCALDATADIR=/var -DFULL_SHARE_DIR=/usr/local/share/manticore Built on FreeBSD amd64 Stack bottom = 0x8cff68a40, thread stack size = 0x20000 Trying manual backtrace: Something wrong with thread stack, manual backtrace may be incorrect (fp=0x8cff65fa0) Stack looks OK, attempting backtrace. 0xdc291a 0x0 0x827f8411f 0x7ffffffff8a3 0xe7ca2b 0xe7cca7 0xeb0efb 0x1 0x1 Something wrong in frame pointers, manual backtrace failed (fp=8286c3168)

tomatolog commented 1 year ago

вам нужно использовать символы от вашей версии и с помощью gdb получить читаемый стек падения как описано у нас в документации Crashes

потому, что в backtrace который вы запостили не хватает читаемого стека - стек падения демона и причина, которая вызывает креш - не понятны

sanikolaev commented 1 year ago

Что ещё будет полезно:

LEO111 commented 1 year ago

Повторился краш, беда в том что по FreeBSD нет ID потока.

server.log gdb.log

LEO111 commented 1 year ago

Что ещё будет полезно:

  • инструкция по сборке
  • данные и конфиг, на которых воспроизводится крэш

Сборка на чистой FreeBSD 13.2-RELEASE-p3 FreeBSD 13.2-RELEASE-p3 GENERIC amd64

Без дополнительных параметров, как в инструкции.

Конфиг:

searchd {
#query_log=/var/log/manticoresearch/slow.log
#query_log_min_msec = 1000 - кстати не работает, валится в лог всё
log=/var/log/manticoresearch/server.log
attr_flush_period = 900
    listen = 192.168.0.2:9306:mysql
    pid_file = /usr/local/var/run/manticore/searchd.pid
    data_dir = /var/db/manticoresearch/data
    query_log_format = sphinxql
        auto_optimize = 0
        binlog_flush = 1
        binlog_max_log_size = 32M
threads=50
thread_stack=8M
subtree_hits_cache = 16M
secondary_indexes = 1
read_buffer_hits = 8M
client_timeout = 5s
}

common {
        lemmatizer_base = /usr/local/share/manticore/
}
LEO111 commented 1 year ago

Причем завал бывает как на REPLACE, так и на INSERT, и так же валится на банальном select, при этом после рестарта тот же запрос на которой крашились, к крашу не приводит и нормально отрабатывает.

sanikolaev commented 1 year ago

А на dev-версии повторяется?

LEO111 commented 1 year ago

Сейчас попробую, затупил слегка.

LEO111 commented 1 year ago

Аналогичная история

Manticore 6.2.13 e8e0b8749@230924 dev Handling signal 11 -------------- backtrace begins here --------------- Program compiled with Clang 14.0.5 Configured with flags: Configured with these definitions: -DUSE_SYSLOG=1 -DWITH_GALERA=1 -DWITH_RE2=1 -DWITH_RE2_FORCE_STATIC=1 -DWITH_STEMMER=1 -DWITH_STEMMER_FORCE_STATIC=1 -DWITH_NLJSON=1 -DWITH_UNIALGO=1 -DWITH_ICU=1 -DWITH_ICU_FORCE_STATIC=1 -DWITH_SSL=1 -DWITH_ZLIB=1 -DWITH_ZSTD=1 -DDL_ZSTD=1 -DZSTD_LIB=libzstd.so.1 -DWITH_CURL=1 -DDL_CURL=1 -DCURL_LIB=libcurl.so.4 -DWITH_ODBC=1 -DDL_ODBC=1 -DODBC_LIB=libodbc.so.2 -DWITH_EXPAT=1 -DDL_EXPAT=1 -DEXPAT_LIB=libexpat.so.1 -DWITH_ICONV=1 -DWITH_MYSQL=1 -DDL_MYSQL=1 -DMYSQL_LIB=libmariadb.so.3 -DWITH_POSTGRESQL=1 -DDL_POSTGRESQL=1 -DPOSTGRESQL_LIB=libpq.so.5 -DLOCALDATADIR=/var -DFULL_SHARE_DIR=/usr/local/share/manticore Built on FreeBSD amd64 Stack bottom = 0x8b851b940, thread stack size = 0x20000 Trying manual backtrace: Something wrong with thread stack, manual backtrace may be incorrect (fp=0x8b8519420) Stack looks OK, attempting backtrace. 0xe7c24a 0x8b8519590 0x8278b711f 0x7ffffffff8a3 0xf6b57a 0xf66a46 0xf67763 0x1 Something wrong in frame pointers, manual backtrace failed (fp=829496168) Trying boost backtrace: 0# short in /usr/local/bin/searchd 1# signed char restrict complex in /usr/local/bin/searchd 2# unsigned int128 in /lib/libthr.so.3 3# unsigned int128 in /lib/libthr.so.3 4# 0x00007FFFFFFFF8A3 5# unsigned long in /lib/libc.so.7 6# short in /usr/local/bin/searchd 7# SqlServe(std::1::unique_ptr<AsyncNetBuffer_c, std::1::default_delete >) in /usr/local/bin/searchd 8# MultiServe(std::1::unique_ptr<AsyncNetBuffer_c, std::1::default_delete >, std::__1::pair<int, unsigned char>, Proto_e) in /usr/local/bin/searchd 9# NetActionAccept_c::NetLoopDestroying() in /usr/local/bin/searchd

-------------- backtrace ends here ---------------

LEO111 commented 1 year ago

gdb6.2.13.log

sanikolaev commented 1 year ago

Попробуйте сделать воспроизводимый кейс, для этого можно:

tomatolog commented 1 year ago

в обоих дампах GDB - просто набор случайных символов, которые не относятся друг к другу, такое впечатление что символы и бинарник не совпадают

LEO111 commented 1 year ago

в обоих дампах GDB - просто набор случайных символов, которые не относятся друг к другу, такое впечатление что символы и бинарник не совпадают

Во FreeBSD core создается в рабочем каталоге /var/db/manticoresearch/data/searchd.core и других нет, далее всё по инструкции...

Сделал сейчас со свежего краша (периодичность раз в 30 минут где-то), получилось намного меньше

gdb6.2.13-2.log

LEO111 commented 1 year ago
  • накатить всё из /var/log/manticoresearch/slow.log

Не очень понял как это?

sanikolaev commented 1 year ago

Не очень понял как это?

Для начала так:

mysql -P9306 -h0 < slow.log
LEO111 commented 1 year ago
  • если покрэшится

Сделал, не крашится если те же запросы одним потоком закидывать из логов. Я и ранее писал, что крашится на очень разных запросах, связи нет, при этом повторение этих же запросов к крашу не приводит.

У меня подозрение что дело не в данных, их относительно не много, и не в запросах, а в интенсивности, очень много идет обновлений данных, прилично выборок и такое ощущение что под FreeBSD слетает механизм потоков или что-то из этой серии.

sanikolaev commented 1 year ago

а в интенсивности, очень много идет обновлений данных

Если есть опыт в PHP, то вот скрипт, который я обычно использую для эмуляции нагрузки в несколько потоков:

#!/usr/bin/php
<?php
if (count($argv) < 4) die("Usage: ".__FILE__." <batch size> <concurrency> <docs>\n");

// This function waits for an idle mysql connection for the $query, runs it and exits
function process($query) {
    global $all_links;
    global $requests;
    global $latencies;
    foreach ($all_links as $k=>$link) {
        if (@$requests[$k]) continue;
        mysqli_query($link, $query, MYSQLI_ASYNC);
        @$requests[$k] = microtime(true);
        return true;
    }
    do {
        $links = $errors = $reject = array();
        foreach ($all_links as $link) {
            $links[] = $errors[] = $reject[] = $link;
        }
        $count = @mysqli_poll($links, $errors, $reject, 0, 1000);
        if ($count > 0) {
            foreach ($links as $j=>$link) {
                $res = @mysqli_reap_async_query($links[$j]);
                foreach ($all_links as $i=>$link_orig) if ($all_links[$i] === $links[$j]) break;
                if ($link->error) {
                    echo "ERROR in '".substr($query, 0, 100)."...': {$link->error}\n";
                    if (!mysqli_ping($link)) {
                        echo "ERROR: mysql connection is down, removing it from the pool\n";
                        unset($all_links[$i]); // remove the original link from the pool
                        unset($requests[$i]); // and from the $requests too
                    }
                    return false;
                }
                if ($res === false and !$link->error) continue;
                if (is_object($res)) {
                    mysqli_free_result($res);
                }
                $latencies[] = microtime(true) - $requests[$i];
                $requests[$i] = microtime(true);
                mysqli_query($link, $query, MYSQLI_ASYNC); // making next query
                return true;
            }
        };
    } while (true);
    return true;
}

$t = microtime(true);
$all_links = [];
$requests = [];
$latencies = [];
$c = 0;
for ($i=0;$i<$argv[2];$i++) {
  $m = @mysqli_connect('127.0.0.1', '', '', '', 9315);
      if (mysqli_connect_error()) die("Cannot connect to Manticore\n");
      $all_links[] = $m;
//      mysqli_query($all_links[0], "drop table if exists user$i");
//      mysqli_query($all_links[0], "create table user$i(area text, age int, active bit(1)) hitless_words='all' rt_mem_limit='16M'");
  }

// init
mysqli_query($all_links[0], "drop table if exists user");
mysqli_query($all_links[0], "create table user(area text, age int, active bit(1)) hitless_words='all' rt_mem_limit='16M'");

$batch = [];
//$query_start = "insert into user".rand(0,$argv[2])."(id, area, age, active) values ";
$query_start = "insert into user(id, area, age, active) values ";

$error = false;
while (count($all_links) and $c < $argv[3]) {
  $batch[] = "(0,'".substr(md5(rand()), 0, 6)."',".rand(5,15).",".rand(0,1).")";
  $c++;
  if (count($batch) == $argv[1]) {
    if (!process($query_start.implode(',', $batch))) {
      $error = true;
      break;
    }
    $batch = [];
  }
}
if (!$error and count($all_links)) process($query_start.implode(',', $batch));
echo "finished inserting\n";
echo "Total time: ".(microtime(true) - $t)."\n";
LEO111 commented 1 year ago

Если есть опыт в PHP, то вот скрипт, который я обычно использую для эмуляции нагрузки в несколько потоков

У нас по сути тоже делают клиенты. И вот вчера взял небольшой сервер, накатил Debian, поставил Manticore и подсадил данные. Те же самые данные, с той же самой нагрузкой по клиентам, на Debian краша нет, работает уже больше 7 часов без единого варнинга в логе. То есть проблема именно в связке Мантикора-Фряха.

tomatolog commented 1 year ago

вы можете на машине где случаются креши, поставить docker и запустить мантикору в контейнере, из образа который мы предоставляем - чтобы проверить, когда вы дадите такую же нагрузку на демон в контейнере, на таком же железе - будет ли креш

githubmanticore commented 1 year ago

➤ Aleksey N. Vinogradov commented:

btw, threads=50 явно лишнее. Если только у вас не 50-ядерная машина. Нынешний способ работы подразумевает потоки по числу ядер (если не ставить руками threads - всё должно само завестись, как надо). При бОльшем числе (чем число ядер) никаких положительных эффектов не замечено (т.е. быстрее работать уже не будет). Зато потребует больше памяти, в случае крешей выдаст гораздо более длинные простыни бэктрейсов, ну и внутренне создаст больше беспорядка

sanikolaev commented 1 year ago

У нас по сути тоже делают клиенты.

Можете тогда убедиться, что с моим скриптом оно крэшится? У меня freebsd под рукой нет.