Berkeley DB: 在c api调用中异常退出导致卡在 futex_wait 调用-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

Berkeley DB: 在c api调用中异常退出导致卡在 futex_wait 调用

2016-06-16 14:45:50 2301 2

C开发,使用berkeley db 4.3 (/usr/lib64/libdb-4.3.so) on RHEL5.6 with kernel 2.6.18-238_xen_AMD64.

在我的测试中 (写入 1,000,000 key/value pairs), 如果某个进程在对db进行操作的过程中异常退出(ctrl + c, kill, or assert fails) , 此后对db的打开都会被block. 使用strace可以看出,进程卡在了一个 futex(ptr_to_something, FUTEX_WAIT, 2, NULL) 调用。之前它刚打开 __db.00x(e.g __db.001, __db.002, __db.003) .

目前我所知的唯一方法就是删掉 __db.00x 文件,后续测试表明数据库并未损坏,仍可以正常读写。这个出方法基本可以满足我的需求,但是我想知道是否有更好、或者说更优雅的处理方案。

下面列出一些strace的输出,以及用户操作db的代码,也许会有帮助。

some of the strace stderr

...  
open("__db.001", O_RDWR)                = 3  
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0  
fstat(3, {st_mode=S_IFREG|0640, st_size=24576, ...}) = 0  
close(3)                                = 0  
open("__db.001", O_RDWR)                = 3  
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0  
mmap(NULL, 24576, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0x2afcc4149000  
close(3)                                = 0
futex(0x2afcc4149000, FUTEX_WAIT, 2, NULL **[[stuck here]]**
code to operate the database

全选复制放进笔记typedef DB* db_handle;
db_handle bdb_open(const char *filename, u_int32_t cache_size_mb)
{
    int ret;
    DB_ENV *env;
    db_handle dbp;
    u_int32_t flags = DB_CREATE | DB_THREAD | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_LOCK ;
    u_int32_t gb = cache_size_mb / 1024, mb = cache_size_mb % 1024;

    if (ret = db_env_create(&env, 0)) {
        fprintf(stderr, "db_env_create:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if (ret = env->set_timeout(env, 3 * 1000000, DB_SET_LOCK_TIMEOUT)) {
        fprintf(stderr, "env->set_timeout:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if (ret = env->set_lk_detect(env, DB_LOCK_DEFAULT)) { /* this seems to be of no use in my case */
        fprintf(stderr, "env->set_lk_detect:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if (ret = env->set_cachesize(env, gb, mb * 1024 * 1024, 0)) {
        fprintf(stderr, "env->set_cachesize:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if ((ret = env->open(env, NULL, flags, 0)) != 0) {
        fprintf(stderr, "db_env_open:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if (ret = db_create(&dbp, env, 0)) {
        fprintf(stderr, "db_create:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    if (ret = dbp->open(dbp, NULL, filename, NULL, DB_BTREE, flags, 0664)) {
        fprintf(stderr, "dbp->open:%d, %s\n", ret, db_strerror(ret));
        exit(EXIT_FAILURE);
    }

    return dbp;
}

int bdb_put(db_handle db, void* key, u_int32_t keylen, void* val, u_int32_t vallen)
{
    DBT dkey, dval;
    bzero(&dkey, sizeof(dkey));
    bzero(&dval, sizeof(dval));
    dkey.data = key, dkey.size = keylen;
    dval.data = val, dval.size = vallen;
    return db->put(db, NULL, &dkey, &dval, 0);
}

int bdb_get(db_handle db, void* key, const u_int32_t keylen,
                          void* buf, u_int32_t buflen, u_int32_t* nwrite)
{
    DBT dkey, dval;
    bzero(&dkey, sizeof(dkey));
    bzero(&dval, sizeof(dval));
    dkey.data = key, dkey.size = keylen;
    dval.data = buf, dval.ulen = buflen, dval.flags = DB_DBT_USERMEM;
    int ret = db->get(db, NULL, &dkey, &dval, 0);
    if (ret == 0 && nwrite != NULL)
        *nwrite = dval.size;
    return ret;
}
取消 提交回答
全部回答(2)
  • jesuszhu_
    2019-07-17 19:40:52

    linux里大部分会睡眠的同步原语都是用futex实现的. 所以你会看见它停在那里. 

    0 0
  • a123456678
    2019-07-17 19:40:52

    因为BDB是嵌入式的数据库操作,多个进程使用就相当于每个进程的代码都要存在一整套BDB的操作,错误处理代码,这个对事务性操作尤其重要。

    0 0
添加回答
相关问答

10

回答

【精品问答合集】Hbase热门问答

hbase小能手 2019-05-29 14:37:26 123030浏览量 回答数 10

20

回答

【大咖问答】对话PostgreSQL 中国社区发起人之一,阿里云数据库高级专家 德哥

阿里ACE 彭飞 2019-07-10 09:36:10 1218703浏览量 回答数 20

145

回答

【新手入门】云服务器linux使用手册

fanyue88888 2012-11-26 17:14:18 159370浏览量 回答数 145

8

回答

OceanBase 使用动画(持续更新)

mq4096 2019-02-20 17:16:36 340382浏览量 回答数 8

22

回答

爬虫数据管理【问答合集】

我是管理员 2018-08-10 16:37:41 148496浏览量 回答数 22

3

回答

请问postgres实时同步数据到mysql数据库有什么好的方案吗?

toni3 2019-06-29 14:55:43 117135浏览量 回答数 3

2

回答

mySQL数据库报错You have an error in your SQL syntax

落地花开啦 2016-02-14 16:09:24 133118浏览量 回答数 2

39

回答

安全组详解,新手必看教程

我的中国 2017-11-30 15:23:46 262803浏览量 回答数 39

82

回答

OSS入门教程

belle.zhoux 2014-07-07 17:14:27 158127浏览量 回答数 82

21

回答

请教一下数据量有100万条左右要什么配置?

易网网络 2013-03-27 15:18:02 193505浏览量 回答数 21
+关注
0
文章
14879
问答
问答排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载