深入理解mysql之BDB系列(1)

---BDB相关基础知识

作者:杨万富

一:BDB体系结构

1.1.BDB体系结构

BDB总体的体系结构如图1.1所看到的,包括五个子系统(见图1.1中相关数)。1)数据存取子系统,2)事务子系统,3)锁子系统,4)内存池管理子系统,5)日志子系统。

在一个应用程序中,并不一定须要全然具备这5大子系统。

假设程序仅仅使用了数据存取子系统,它的体系结构如图1.2。在图1.2中,我们仅仅使了两个子系统:数据存取以及内存池子系统。(备注:另外三个子系统在BDB系统中隐式调用)

1.2.子系统的介绍

1)数据存取子系统

数据存取子系统提供多种存取数据库文件的方法:1)B树、2)HASH文件、3)定长记录以及4)变长记录。

对于这四种不同的存取类型,BDB系统提供差点儿一致的接口。比方,要打开一个数据库,都使用DB->open。

有些情况下,为更快的存取效率而不使用事务子系统,数据存取子系统能够单独使用,从而提供更快的存取速度(见图1.2)。

2)事务子系统

事务子系统同意将一系统的操作看作为一个原子操作,或者所有完毕,或者所有取消。能够依据应用的详细情况,设置事务的隔离级别。

事务子系统能够单独使用,适用于须要符合事务特性的应用。

3)锁子系统

锁子系统为BDB提供锁机制,为系统提供读、写控制。能够同意多用户同一时候进行读操作,仅仅同意单用户进行排它的改动操作。通过子系统,申请读、写权限,一旦申请成功,便可进行相关操作。事务子系统利用锁机制来实现多个事务的并发控制。

锁子系统能够被应用程序单独使用,为应用提供一个灵活的、高速的、可设置的锁管理。

4)内存池管理子系统

该子系统为多进程(或多线程)共享存取数据提供可能。须要页数据时,假设数据已经缓冲在内存池中,则直接使用,否则将新的页读到内存池中供用户使用。在必要的时候,将改动的页数据进行刷盘操作。

该子系统能够被应用程序单独使用。内存池管理子系统为应用提供灵活的、面向页、数据缓冲管理。

5)日志子系统

该子系统採用先写日志先写数据的策略,用于支持事务子系统进行数据恢复,保证数据一致性。该子系统不能被应用程单独使用,仅仅能做为事务子系统的调用模块。

二:BDB环境(Environment)

2.1.概述

BDB环境是对一个或多个数据库、日志文件以及区域文件的一个封装。区域文件能够理解为共享内存池,用来保存相似缓冲页的BDB环境信息。仅仅有数据库文件是平台独立的,能够在不同的byte-order机器上进行移动。日志文件能够在同byte-order的机器上进行移动。可是,区域文件对特定的机器是唯一的,不能与其他类型机器进行日志文件的移动,甚至对于不同版本号的操作系统,尽管机器类型同样却也不能移动。

管理BDB环境最简单的方法就是创建一个home文件夹,在该文件夹中存储须要共享环境的文件。假设须要使用home文件夹(比方文件夹myhome),必须在应用程序执行之前创建好该文件夹(比方在工作文件夹下创建一个命令为myhome的文件夹),由于BDB本身不会为用户创建home文件夹。BDB环境通过文件夹名进行标识。

一个环境能够被多进程以及多线程共享。一个环境能够引用系统其他文件夹的资源,应用程序经常选择将资源分布到不同的文件夹或者磁盘,以此来提升程序性能。虽然如此,在默认情况下,数据库文件、共享区域(包含锁、日志缓冲区、内存池、事务共享内存区域)以及日志文件存储在一个同层次文件夹中(home文件夹中,能够包含其他的比方,比方在当中创建一个mydata文件夹用来存储用户的数据库文件)。

共享同一个环境的全部应用,它们彼此之间是互相信任的。它们能互相訪问对方的数据,由于这些数据都是放在共享区域中的。它们共享相似于buffer以及锁之类的资源。与此同一时候,假设多个应用想要使用同一个数据库,而且须要它们之间保持一致性,则必须共享同一个环境。

2.2.创建BDB环境

BDB环境是通过db_env_create以及DB_ENV->open接口来创建和描写叙述的。在须要定制的地方,比方将日志文件存储到一个单独的磁盘,或者选择一个特定的值做为cache的大小,应用通过环境配置文件或者将參数传递给DB_ENV处理函数来实现定制。

一旦一个环境被创建,被指定相关路径的数据库文件,都将相对环境的home文件夹来创建。用相对路径同意整个环境的轻易的移动。简化了在不同文件夹和不同系统中重建和恢复的步骤。

一旦应用程序首先通过db_env_create方法获得一个环境句柄,然后调用DB_ENV->open来创建或增加数据库环境。这里有非常多选项你能够在调用DB_ENV->open时来定制你的环境。这些选项大致能够分为四类:

1)子系统初始化选项:

这些标志指明哪些bdb子系统将由于环境被初始化,和哪些操作将自己主动发生当数据库在环境中被訪问的时候。这些标志包含DB_INIT_CDB,DB_INIT_LOCK,DB_INIT_LOG,DB_INIT_MPOOL,以及DB_INIT_TXN。DB_INIT_CDB标志为bdb并发数据存储做初始化工作。其他标志初始化单个子系统。比方,当DB_INIT_LOCK标志被指定,应用程序读写在这个环境中打开的数据库时,将使用locking子系统以确保它们不覆盖对方的对数据的修改。

2)恢复选项:

这些标志包含DB_RECOVER和DB_RECOVER_FATAL,它们表明在环境被打开且在正常使用之前,恢复将要进行。

3)命名选项:

这些标志包含DB_USE_ENVIRON和DB_USE_ENVIRON_ROOT,改动怎样在环境给文件命名。

4)混杂选项:

除非前面的三类之外,另一些混杂选项,比方,DB_CREATE选项使底数据库文件被创建时是必需的。

对于大多数应用,或者只指定DB_INIT_MPOOL,或者指定全部的四个子系统的初始化标志(DB_INIT_MPOOL,DB_INIT_LOCK,DB_INIT_LOG以及DB_INIT_TXN)。前者不过想简单用一些主要的訪问方法以及一个共享缓冲池,没有考虑应用程序或系统出现问题时的可恢复性。后者是一些须要提供可恢复性的应用。在一些罕见的情况下,也有可能是其他的初始化标志的组合。

DB_RECOVER标志在当应用启动执行时做一些必需的数据库恢复的时候被指定。也就是说,在上一次执行过程中假设系统或应用程序出现问题,打算在再次执行前将数据恢复到一致性状态。只是,在没有不论什么数据须要恢复的情况下,指定这个标志也不为错。

DB_RECOVER_FATAL标志有更特殊的用途。它运行灾难性的数据库恢复,通常须要做一些初始化的安排;也就是说归档日志文件被带回到文件系统。应用程序通常不指定该标志。做为替代,在这样的罕见的情况,应该使用db_recover函数。

以下是一个简单的为事务程序打开一个数据库环境的样例:

DB_ENV *

db_setup(home, data_dir, errfp, progname)

char *home, *data_dir, *progname;

FILE *errfp;

{

DB_ENV *dbenv;

int ret;

/*

* Create an environment and initialize it for additional error

* reporting.

*/

if ((ret = db_env_create(&dbenv, 0)) != 0) {

fprintf(errfp, "%s: %s/n", progname, db_strerror(ret));

return (NULL);

}

dbenv->set_errfile(dbenv, errfp);

dbenv->set_errpfx(dbenv, progname);

/*

* Specify the shared memory buffer pool cachesize: 5MB.

* Databases are in a subdirectory of the environment home.

*/

if ((ret = dbenv->set_cachesize(dbenv, 0, 5 * 1024 * 1024, 0)) != 0) {

dbenv->err(dbenv, ret, "set_cachesize");

goto err;

}

if ((ret = dbenv->set_data_dir(dbenv, data_dir)) != 0) {

dbenv->err(dbenv, ret, "set_data_dir: %s", data_dir);

goto err;

}

/* Open the environment with full transactional support. */

if ((ret = dbenv->open(dbenv, home, DB_CREATE |

DB_INIT_LOG | DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {

dbenv->err(dbenv, ret, "environment open: %s", home);

goto err;

}

return (dbenv);

err: (void)dbenv->close(dbenv, 0);

return (NULL);

}

2.3.在环境中打开数据库

一旦环境被创建,数据句柄可能在这个环境中打开。这由db_create函数通过指定特定的环境作为參数来实现。

文件命名、数据库操作以及错误处理都将由于这个指定的环境而被做。比如,假设DB_INIT_LOCK或DB_INIT_CDB标志被指定,在环境被创建(create)或被合并(join)时,数据库操作将为应用程序自己主动地运行全部必要的锁操作。

以下是个简单的样例,在一个环境中打开两个数据库:

DB_ENV *dbenv;

DB *dbp1, *dbp2;

int ret;

dbenv = NULL;

dbp1 = dbp2 = NULL;

/*

* Create an environment and initialize it for additional error

* reporting.

*/

if ((ret = db_env_create(&dbenv, 0)) != 0) {

fprintf(errfp, "%s: %s/n", progname, db_strerror(ret));

return (ret);

}

dbenv->set_errfile(dbenv, errfp);

dbenv->set_errpfx(dbenv, progname);

/* Open an environment with just a memory pool. */

if ((ret =

dbenv->open(dbenv, home, DB_CREATE | DB_INIT_MPOOL, 0)) != 0) {

dbenv->err(dbenv, ret, "environment open: %s", home);

goto err;

}

/* Open database #1. */

if ((ret = db_create(&dbp1, dbenv, 0)) != 0) {

dbenv->err(dbenv, ret, "database create");

goto err;

}

if ((ret = dbp1->open(dbp1,

NULL, DATABASE1, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {

dbenv->err(dbenv, ret, "DB->open: %s", DATABASE1);

goto err;

}

/* Open database #2. */

if ((ret = db_create(&dbp2, dbenv, 0)) != 0) {

dbenv->err(dbenv, ret, "database create");

goto err;

}

if ((ret = dbp2->open(dbp2,

NULL, DATABASE2, NULL, DB_HASH, DB_CREATE, 0664)) != 0) {

dbenv->err(dbenv, ret, "DB->open: %s", DATABASE2);

goto err;

}

return (0);

err: if (dbp2 != NULL)

(void)dbp2->close(dbp2, 0);

if (dbp1 != NULL)

(void)dbp2->close(dbp1, 0);

(void)dbenv->close(dbenv, 0);

return (1);

}

2.4.出错处理

db_strerror函数能依据一个bdb的错误返回值返回一个指向错误信息的指针。它能够处理系统的错误也能处理bdb特有的返回值。

比如:

int ret;

if ((ret = dbenv->set_cachesize(dbenv, 0, 32 * 1024, 1)) != 0) {

fprintf(stderr, "set_cachesize failed: %s/n", db_strerror(ret));

return (1);

}

这里也有两个附加的错误处理函数: DB_ENV->err和DB_ENV->errx。

DB_ENV->err函数追加标准错误字符串到已构造好的消息,而DB_ENV->errx不那样。

错误信息能够通过DB_ENV->set_errpfx被配置成总包括一些固定的前缀(比如,应用程序名称)。

比如:

int ret;

dbenv->set_errpfx(dbenv, program_name);

if ((ret = dbenv->open(dbenv, home,

DB_CREATE | DB_INIT_LOG | DB_INIT_TXN | DB_USE_ENVIRON, 0))

!= 0) {

dbenv->err(dbenv, ret, "open: %s", home);

dbenv->errx(dbenv,

"contact your system administrator: session ID was %d",

session_id);

return (1);

}

如果,应用程序名为”my_app”,它企图打开环境文件夹”/tmp/home”且open函数返回权限错误,出错的信息例如以下:

my_app: open: /tmp/home: Permission denied.

my_app: contact your system administrator: session ID was 2

2.5.DB_CONFIG配置文件

差点儿全部能够指定给DB_ENV那些方法的培植信息,也能够通过一个配置文件来指定。假设一命名为DB_CONFIG的文件存在数据库home文件夹下,它将会依照name value的格式被一行行地读入。

NAME与VALUE之间是通过一个或者多个空格来切割,拖尾的空格将被丢弃。空行或以#開始的行,将被忽略。每一行必须同一时候指定NAME以及相相应的VALUE。NAME VALUE是通过手动方式进行编辑的。

DB_CONFIG配置文件的目的是同意管理员定制不依赖于应用程序的环境。比如,能够移动log文件以及数据文件到不同的位置,而不用又一次编译应用程序。另外,DB_CONFIG文件是当数据库环境被打开时读取的,它能够用来覆盖在那曾经配置的规则。比如,能够定义一个更合理的cache大小,来覆盖曾经已经编译到程序中的值。

2.6.文件命名

以下介绍几种可能的为bdb指定命名信息的方法:

1)db_home:为DB->open的db_home參数指定一个非NULL值,它的值将会用来作为数据库的home,以后的文件命名都是相对这个路径。

2)DB_HOME:为环境变量DB_HOME指定值,DB_ENV->被调用时,读取这个值,把它作为数据库home,以后的文件命名都是相对这个路径。

3)DB_ENV方法:这里有三个函数能够影响文件命名,DB_ENV->set_data_dir能够为数据库文件指定一个文件夹。DB_ENV->set_lg_dir能够为log文件指定文件夹。DB_ENV->set_tmp_dir为创建的暂时文件指定文件夹。比如,一个应用程序能够将数据文件、日志文件分别放到不同的文件夹中。

4)DB_CONFIG文件:同样的指定给DB_ENV方法的信息,也能够用DB_CONFIG配置文件来指定。

指定路径的优先级从高究竟是这种:DB_ENV,DB_CONFIG,db_home,DB_HOME,default。假设以上的路径为绝对路径,那么home就是那个绝对路径。假设以上的路径为相对路径,那么将依据当前的工作文件夹计算出home路径。假设什么都没指定,那么默认的将如今的工作文件夹作为home。

比如:

情况一:将全部的文件都放在文件夹/a/database下:

dbenv->open(dbenv, “/a/database”, flags, mode);

情况二:将暂时文件存储到文件夹/b/temporary,其它文件放在/a/database文件夹下:

dbenv->set_temp_dir(dbenv, “/b/temporary”);

dbenv->open(dbenv, “/a/database”, flags, mode);

情况三:将数据文件放在文件夹/a/database/datadir下,日志文件放在文件夹/a/database/logdir文件夹下,其他文件放在文件夹/a/database下。

dbenv->set_lg_dir(dbenv, ”logdir”);

dbenv->set_data_dir(dbenv, “datadir”);

dbenv->open(dbenv, “/a/database”, flags, mode);

情况四:将数据文件放在/a/database/data1和/b/data2文件夹下,其他的文件放在文件夹/a/database下。不论什么数据文件都将被创建在/b/data2文件夹下,由于它是第一个被指定的数据文件夹。

dbenv->set_data_dir(dbenv, “/b/data2”);

dbenv->set_data_dir(dbenv, “data1”);

dbenv->open(dbenv, “/a/database”, flags, mode);

2.7.共享内存区域(shared memory regions)

环境中的每一个子系统都被一个或多个区域(regions),或大块的内存来描写叙述。区域包含全部的每进程和每线程共享信息(包含mutexs),这些组成了bdb环境。这些区域将在三种类型中的一种中被创建,这取决于指定DB_ENV->open方法的标志:

1)DB_PRIVATE:假设这标志被指定,区域将在每进程(per-process)内存中被创建;也就是说由malloc()返回的内存。

假设有不止一个进程訪问环境,这个标志最好不要指定。由于它非常有可能导致数据库腐烂(corruption)和一些不可预期的行为。比如,当server应用程序和bdb公共程序(比如,db_archive,db_checkpoint或者db_stat)都期望訪问这个环境的时候,最好别指定DB_PRIVATE标志。

2)DB_SYSTEM_MEM:假设这个标志被指定,共享区域将在系统内存中创建而不是在文件里。这是一个可选的机制,为了在多个进程和一个进程中的多个线程共享bdb环境。

Bdb所使用的系统内存潜在地非常实用,伴侣不论什么特殊的进程度过生存周期。因此,附加的清除操作是必要当应用程序出现问题后,由于bdb没办法确认,支撑内存区的系统资源是不是还给了系统。

系统内存的使用是依据计算机体系结构而定的。比如,在一个支持X/Open样式共享内存的系统上,比方UNIX系统,shmget(2)和类似的系统V IPC接口被调用。另外,在VxWork系统中使用系统内存。在这些情况下,一个初始的段ID必须在应用程序中被指定,以确保应用程序不互相覆盖对方的数据库环境,所以段创建的数量部是无限制的增长。能够參考DB_ENV->set_shm_key方法获得很多其它的信息。

在Windows平台上,使用DB_SYSTEM_MEM标志是有非常多问题的。由于该操作系统使用引用计数来自己主动地清除页共享对象。另外,默认的共享对象的訪问权限控制,不同于文件,假设是不同用户使用的多进程,这将导致问题。

3)default:假设没有内存相关的标志指定给DB_ENV->open,被文件系统支撑的内存(虚拟内存)将用来存储这些区域(regions)。在UNIX系统上,bdb库将使用POSIX mmap接口。假设mmap不可用,那么unix shmget接口可能被使用,假设它可用的话。

不论什么文件系统中创建的用来支撑区域的文件,将在环境的home文件夹(DB_ENV->open指定)中被创建。这些文件命名为为__db.###(比如,__db.001,__db.002等等)。当区域文件是被文件系统支撑的时候,每个区域相应一个文件将被创建。当区域文件被系统内存来支撑的时候,仅仅有一个文件将仍然被创建,因此这里必须有一熟知的名字在文件系统中,以便多进程能定位到环境所使用的系统共享内存。

统计在环境中的共享内存区域,能够使用db_stat的-e选项来显示。

2.8.安全(security)

以下是当你写bdb应用程序的时候须要考虑的安全问题。

1)数据库环境许可(Database environment permissions)

被bdb数据库环境使用的文件夹,应该有它自己的许可设置,以确保那些没有适当权限的用户不能訪问环境里的文件。应用程序加入用户的訪问许可时(比如,unix的setuid或segid程序),应该细致的检查,不同意违法的使用这些许可,比如訪问环境中的文件。

2)环境变量(Environment variables)

设置DB_USE_ENVIRON和DB_USE_ENVIRON_ROOT标志,和同意在文件命名时使用环境变量都是危急的。设置这些标志,并使用附加的权限(比如,UNIX setuid或segid程序),将潜在地同意那些正常情况下没有权限的用户读写数据库。

3)文件许可(File permission)

默认地,bdb总是创建全部者和所在组可读写的文件(也就是,S_IRUSR,S_IWUSR,S_IRGRP和S_IWGRP;或者在历史性的UNIX系统上使用八进制模块0660)。创建文件的组的全部权限,是基于系统和文件夹的,不被bdb进一步指定。

4)暂时支撑文件(Tempprary backing files

假设一个没有命名的数据库被创建,而cache太小以至于在内存中保持这个数据库bdb将创建一个暂时的物理文件,必要时使它能把数据库的cache页放到磁盘上。在这样的情况下,环境变量,比方TMPDIR可能被用来定位那个暂时文件。虽然暂时支撑文件被创建成仅仅有全部者可读写(S_IRUSR和S_IWUSR,或八进制模式0600在历史性的UNIX系统上),一些文件系统可能不能充分保护被创建在随机文件夹中的暂时文件不被非法訪问。为了绝对安全,应用程序存储敏感数据在未命名的数据库红,应该用DB_ENV->set_tmp_dir方法用已知的许可(known perimissions)指定一个暂时文件夹。

mysql bdb版本_深入理解mysql之BDB系列(1)---BDB相关基础知识相关推荐

  1. mysql核心技术分析_深入理解MySQL核心技术

    前言 第1章 MySQL的历史与架构 MySQL的历史 MySQL的架构 第2章 MySQL源代码基本要点 Unix Shell BitKeeper 准备系统:从BitKeeper树构建MySQL 从 ...

  2. mysql in 原理_深入理解MySql子查询IN的执行和优化

    IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...

  3. mysql recovery参数_深入理解MySQL 5.7 GTID系列(七)binlog_gtid_simple_recovery参数的影响总结...

    想了想还是专门开了一节来总结这个问题: 5.7.6以下中默认 simplified_binlog_gtid_recovery=flase 5.7.6以上中默认 binlog_gtid_simple_r ...

  4. mysql gtid深入_深入理解MySQL 5.7 GTID系列(四):mysql.gtid_executedPREVIOUS GTID EVENT

    之所以把MySQL.GTID_EXECUTED表的作用和PREVIOUS GTID EVENT的改变放到一起进行描述是因为它们后面文章探讨的基础.这部分使用到了我自己使用C语言写的原生BINLOG解析 ...

  5. 深入理解mysql百度网_深入理解mysql

    1.表的优化和列类型选择 表的优化 1,定长和变长分离 2,常用字段和不常用字段分离(不常用字段单独建表) 3,添加冗余字段提高查询(反范式查询(数据统计)) 列类型选择 1,字段类型选择优先级 整形 ...

  6. 水泵怎么做_暖通空调|水泵出入口阀门及相关基础知识

    设计过程中,经常看到或遇到一些设计人员对水泵前后的布置啥阀门或怎么布置阀门提出异议,现就对水泵前后的阀门及相关知识进行浅析,由于水平有限,有不对的地方欢迎指出. <通风与空调工程施工规范> ...

  7. 深入理解mysql之BDB系列(1)---BDB相关基础知识

        深入理解mysql之BDB系列(1) ---BDB相关基础知识 作者:杨万富 一:BDB体系结构 1.1.BDB体系结构 BDB整体的体系结构如图1.1所示,包含五个子系统(见图1.1中相关数 ...

  8. mysql 锁机制 mvcc_轻松理解MYSQL MVCC 实现机制

    轻松理解MYSQL MVCC 实现机制 轻松理解MYSQL MVCC 实现机制 #### 1. MVCC简介 ##### 1.1 什么是MVCC MVCC是一种多版本并发控制机制. ##### 1.2 ...

  9. 【MySQL笔记】正确的理解MySQL的MVCC及实现原理

    MVCC多版本并发控制 如果觉得对你有帮助,能否点个赞或关个注,以示鼓励笔者呢?!博客目录 | 先点这里 !首先声明,MySQL 的测试环境是 5.7 前提概要 什么是 MVCC 什么是当前读和快照读 ...

最新文章

  1. 2018/11/29 一个64位操作系统的设计与实现 02 (安装nasm)
  2. Python大佬抓取了招聘信息并告诉你哪种Python 程序员最赚钱
  3. 单电源运算放大器全波整流电路_几种二极管整流电路原理图解。
  4. 网络推广计划浅析外链发布要遵循的几点小技巧!
  5. python decorator模块_Python decorator module
  6. [JZOJ5836] Sequence
  7. python去掉人像白边_python 使用plt画图,去除图片四周的白边方法
  8. eplan备份时卡顿_EPLAN卡顿了怎么办?
  9. STM32F1xx系列单片机通过程序获取MCU信息
  10. UVA10049 Self-describing Sequence【数列】
  11. 23种设计模式(十)对象创建之构建器
  12. (14) 常用管理类软件需求征集 -- 组织机构管理
  13. 《剑指offer》面试题6——重构二叉树——已知 前序遍历和中序遍历,求后序遍历(C++)
  14. 国内的商业与开源 CMS
  15. PHP根据经纬度计算距离
  16. 推荐windows下 DNS本地化工具 TreeWalk DNS 8.21
  17. java:编写一个求平方的窗体
  18. 数论基础,从入门到入门
  19. 双机热备、双机互备、双机双工之间的区别
  20. 阿里云小蜜优势与应用场景

热门文章

  1. 中台之上(六):如何为一个商业银行设计业务架构?
  2. Redis学习手册1—数据结构之字符串
  3. “华为手机”和“荣耀手机”哪个好?看完不迷路的文章来了!
  4. 洛谷P1736 创意吃鱼法
  5. 股票量化交易的优点和缺点分别有哪些?
  6. 2021.11.09 - 144.祖玛游戏
  7. AI 世界里,挖掘机「生产」哪家强?
  8. pycharm 注释
  9. IBM DS3500存储添加控制器
  10. 专题学习1 Cproblem—马走日