2013-06-10 6 views
1

5 개의 데이터베이스가있는 응용 프로그램에서 LevelDB를 사용하고 있습니다. 각 데이터베이스는 max_open_files = 64 옵션으로 열립니다.LevelDB : IO 오류 : XXX.sst : 열린 파일이 너무 많습니다.

ulimit -Sn은 운영 체제가 1024 개의 파일로 제한된다는 것을 보여줍니다. 한계를 2048로 설정하면 문제가 해결됩니다. 이 응용 프로그램을 사람들에게 배포하기 때문에 사용자가 운영 체제를 구성하지 않아도 기본적으로 작동하는 기본값이 있어야합니다.

leveldb::Status status = db_spends_->Get(
    leveldb::ReadOptions(), spent_slice, &raw_spend); 
if (!status.ok()) 
{ 
    std::cerr << "fetch_spend: " << status.ToString() << std::endl; 
    return false; 
} 

나는 많은 오류가 발생하며 전혀 읽을 수 없습니다.

"fetch_spend: IO error: XXXX.sst: Too many open files" 

database라는 하나 개의 하위 디렉토리에 5 데이터베이스가 있습니다

$ ls 
addr block block_hash spend tx 
$ du -sh . 
16G . 
$ du -sh * 
2.6G addr 
653M block 
7.2M block_hash 
2.6G spend 
9.4G tx 
$ for i in `ls`; do echo $i; ls $i | wc -l; done 
addr 
1279 
block 
333 
block_hash 
10 
spend 
1433 
tx 
5252 

나는 각 .sst 파일 LevelDB 내부 2 MB 제한을 변경하려면, 그러나 조정 것 내가하지 않습니다 Google에서만이 패치를 보았습니다 : https://github.com/basho/leveldb/pull/7

저는 우분투 13.04 64 비트를 사용하고 있습니다.

다음은 데이터베이스를 여는 데 사용하는 코드입니다. leveldb::DB::Open() 호출 전에 open_options.max_open_files을 표시하면 예상대로 64가 표시됩니다.

bool open_db(const std::string& prefix, const std::string& db_name, 
    std::unique_ptr<leveldb::DB>& db, leveldb::Options open_options) 
{ 
    using boost::filesystem::path; 
    path db_path = path(prefix)/db_name; 
    leveldb::DB* db_base_ptr = nullptr; 
    leveldb::Status status = 
     leveldb::DB::Open(open_options, db_path.native(), &db_base_ptr); 
    if (!status.ok()) 
    { 
     log_fatal(LOG_BLOCKCHAIN) << "Internal error opening '" 
      << db_name << "' database: " << status.ToString(); 
     return false; 
    } 
    // The cointainer ensures db_base_ptr is now managed. 
    db.reset(db_base_ptr); 
    return true; 
} 

... 

// Create comparator for blocks database. 
depth_comparator_.reset(new depth_comparator); 
// Open LevelDB databases 
const size_t cache_size = 1 << 20; 
// block_cache, filter_policy and comparator must be deleted after use! 
open_options_.block_cache = leveldb::NewLRUCache(cache_size/2); 
open_options_.write_buffer_size = cache_size/4; 
open_options_.filter_policy = leveldb::NewBloomFilterPolicy(10); 
open_options_.compression = leveldb::kNoCompression; 
open_options_.max_open_files = 64; 
open_options_.create_if_missing = true; 
// The blocks database options needs its depth comparator too. 
leveldb::Options blocks_open_options = open_options_; 
blocks_open_options.comparator = depth_comparator_.get(); 
if (!open_db(prefix, "block", db_blocks_, blocks_open_options)) 
    return false; 
if (!open_db(prefix, "block_hash", db_blocks_hash_, open_options_)) 
    return false; 
if (!open_db(prefix, "tx", db_txs_, open_options_)) 
    return false; 
if (!open_db(prefix, "spend", db_spends_, open_options_)) 
    return false; 
if (!open_db(prefix, "addr", db_address_, open_options_)) 
    return false; 

내가 max_open_files = 20 설정하더라도 나는 여전히 같은 문제를 얻을.

답변

2

max_option_files를 < 74로 설정하면 최근까지는 옵션 설명과 달리 수백 개의 파일 설명자가 사용되었을 때 병적 동작이 발생할 수있었습니다. (Leveldb 클램프의 최신 버전은 74의 바닥을 제한합니다.) ~ 80로 설정하면 효과가 있습니까? 그렇지 않고 여전히 문제가 발생하면 나쁜 행동을 볼 때 lsof의 적절한 주문을 실행할 수 있습니까? 그러면 파일 설명자가 어디로 갈지 알려줍니다.

+0

높은 숫자로 설정하면 더 잘 작동합니다. – genjix