columnar icon indicating copy to clipboard operation
columnar copied to clipboard

crash on select when too many ft fields

Open sanikolaev opened this issue 3 years ago • 0 comments

If you run this script:

#!/usr/bin/php  
<?php  
if (count($argv) < 5) die("Usage: ".__FILE__." <batch size> <concurrency> <docs> <number of fields>\n");  
  
// This function waits for an idle mysql connection for the $query, runs it and exits  
function process($query) {  
    global $all_links;  
    global $requests;  
    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: {$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);  
                }  
                $requests[$i] = microtime(true);  
		mysqli_query($link, $query, MYSQLI_ASYNC); // making next query  
                return true;  
            }  
        };  
    } while (true);  
    return true;  
}  
  
$all_links = [];  
$requests = [];  
$c = 0;  
for ($i=0;$i<$argv[2];$i  ) {  
  $m = @mysqli_connect('127.0.0.1', '', '', '', 9306);  
      if (mysqli_connect_error()) die("Cannot connect to Manticore\n");  
      $all_links[] = $m;  
  }  
  
// init  
mysqli_query($all_links[0], "drop table if exists t2");  
$create = "create table t2(";  
$ar=[]; for ($n=1;$n<=$argv[4];$n  ) $ar[] = "f$n text"; $create .= implode(',', $ar);  
$create .= ", s string) engine='columnar'";  
mysqli_query($all_links[0], $create);  
  
$batch = [];  
$query_start = "insert into t2(";  
$ar=[]; for ($n=1;$n<=$argv[4];$n  ) $ar[] = "f$n"; $query_start .= implode(',', $ar);  
$query_start .= ",s) values ";  
  
srand(1);  
echo "preparing...\n";  
$error = false;  
$cache_file_name = '/tmp/dmitry'.md5($query_start).'_'.$argv[1].'_'.$argv[3];  
$c = 0;  
if (!file_exists($cache_file_name)) {  
    $batches = [];  
    while ($c < $argv[3]) {  
      $ar = [];  
      for ($n=0;$n<$argv[4];$n  ) $ar[] = "'".substr(md5(rand()), 0, 4)."'";  
      $ar[] = "'".uniqid()."'";  
      $batch[] = "(".implode(',', $ar).")";  
      $c  ;  
      if (floor($c/1000) == $c/1000) echo "\r".($c/$argv[3]*100)."%       ";  
        if (count($batch) == $argv[1]) {  
          $batches[] = $query_start.implode(',', $batch);  
          $batch = [];  
        }  
    }  
    if ($batch) $batches[] = $query_start.implode(',', $batch);  
    file_put_contents($cache_file_name, serialize($batches));  
} else {  
    echo "found in cache\n";  
    $batches = unserialize(file_get_contents($cache_file_name));  
}  
  
echo "querying...\n";  
  
$t = microtime(true);  
  
foreach ($batches as $batch) {  
  if (!process($batch)) die("ERROR\n");  
}  
  
// wait until all the workers finish  
do {  
  $links = $errors = $reject = array();  
  foreach ($all_links as $link)  $links[] = $errors[] = $reject[] = $link;  
  $count = @mysqli_poll($links, $errors, $reject, 0, 100);  
} while (count($all_links) != count($links)   count($errors)   count($reject));  
  
echo "finished inserting\n";  
echo "Total time: ".(microtime(true) - $t)."\n";  
echo round($argv[3] / (microtime(true) - $t))." docs per sec\n";  

like this:

rm /tmp/dmitry*  
php load_sql_columnar_crash.php 1000 4 50000 47  

against version Server version: 5.0.3 aea4e54ff@220727 dev (columnar 1.16.1 637ddc6@220727) git branch HEAD (no branch)

then the following will cause a crash:

snikolaev@dev:~$ mysql -P9306 -h0 -e "select * from t2 where s='abc'"  
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query  

The config is :

snikolaev@dev:~$ cat /etc/manticoresearch/manticore.conf  
common {  
    plugin_dir = /usr/local/lib/manticore  
    lemmatizer_base = /var/lib/manticore/  
}  
  
searchd {  
    listen = 127.0.0.1:9312  
    listen = 127.0.0.1:9306:mysql  
    listen = 127.0.0.1:9308:http  
    log = /var/log/manticore/searchd.log  
    query_log = /var/log/manticore/query.log  
    pid_file = /var/run/manticore/searchd.pid  
    data_dir = /var/lib/manticore  
    query_log_format = sphinxql  
    binlog_max_log_size = 1M  
    max_open_files = max  
    max_packet_size = 128M  
}  

Notes:

  • it crashes in the latest release as well
  • if I remove engine='columnar' it doesn't crash
  • if I lower the number of ft fields to 40 (php load_sql_columnar_crash.php 1000 4 50000 40) it doesn't crash
  • when it crashes you have to remove the index dir manually, otherwise you can't create the table again:
    nikolaev@dev:~$ mysql -P9306 -h0 -e "select * from t2 where s='abc'"  
    RROR 2013 (HY000) at line 1: Lost connection to MySQL server during query  
    nikolaev@dev:~$ sudo cat /var/lib/manticore/manticore.json  
      
    "clusters":	{  
    },  
    "indexes":	{  
    	"chinese_tokenization":	{  
    		"type":	"rt",  
    		"path":	"chinese_tokenization"  
    	},  
    	"t1":	{  
    		"type":	"rt",  
    		"path":	"t1"  
    	},  
    	"t2":	{  
    		"type":	"rt",  
    		"path":	"t2"  
    	}  
    }  
    snikolaev@dev:~$mysql -P9306 -h0 -e "show tables"  
    ---------------------- ------   
     Index                | Type |  
    ---------------------- ------   
     chinese_tokenization | rt   |  
     t1                   | rt   |  
    ---------------------- ------   
    
  • archive of the index is t2.tgz
  • the crash looks really bad (no crashlog):
    Wed Jul 27 18:14:16.110 2022] [334175] prereading 2 indexes  
    Wed Jul 27 18:14:16.110 2022] [334171] accepting connections  
    Wed Jul 27 18:14:16.120 2022] [334175] preread 2 indexes in 0.010 sec  
    Wed Jul 27 18:19:12.955 2022] [334174] rt: index t2: diskchunk 0(1), segments 29  saved in 0.443840 (0.535320) sec, RAM saved/new 48616545/0 ratio 0.950000 (soft limit 127506841, conf limit 134217728)  
    Wed Jul 27 18:21:04.950 2022] [327687] watchdog: main process 334171 killed dirtily with signal 11, core dumped, will be restarted  
    Wed Jul 27 18:21:04.950 2022] [327687] watchdog: main process 337621 forked ok  
    Wed Jul 27 18:21:04.951 2022] [337621] starting daemon version '5.0.3 aea4e54ff@220727 dev (columnar 1.16.1 637ddc6@220727)' ...  
    Wed Jul 27 18:21:04.951 2022] [337621] listening on 127.0.0.1:9312 for sphinx and http(s)  
    Wed Jul 27 18:21:04.951 2022] [337621] listening on 127.0.0.1:9306 for mysql  
    

sanikolaev avatar Jul 27 '22 16:07 sanikolaev