BEGIN IMMEDIATE/EXCLUSIVE
do in Berkeley DB?
DB_CONFIG
file to override default settings?
SQLITE_BUSY
easily?
sqlite3_prepare()
, …
Yes, conceptually a Berkeley DB database is a single relational database table. Also you can consider key/value pairs each as a single row in a table where the columns are data encoded within either the key or the value by the application.
No. If you own a commercial license, you can continue to download and use new releases of Berkeley DB under the terms of your commercial license. Berkeley DB continues to be dual license, open source or commercial. The open source license has changed from the (proprietary) Sleepycat license to the (industry standard) AGPL.
Take a minute to read these two sections of the sections of the Berkeley DB Reference Guide, they cover this topic in great detail.
When using the C API, the DB
and DB_ENV
handles each contain an app_private
field intended to be used to reference application-specific information. See the db_create and db_env_create documentation for more information.
In the C++ or Java APIs, the easiest way to associate application-specific data with a handle is to subclass the Db
and DbEnv
handles, for example subclassing Db
to get MyDb
. Objects of type MyDb
will still have the Berkeley DB API methods available on them, and you can put any extra data or methods you want into the MyDb
class. If you are using callback APIs that take Db
or DbEnv
arguments (for example, the Db.set_bt_compare() method), these will always be called with the Db
or DbEnv
objects you create. So if you always use MyDb
objects, you will be able to take the first argument to the callback function and cast it to a MyDb
(in C++, cast it to (MyDb*)). That will allow you to access your data members or methods.
Berkeley DB does optionally include strong cryptographic support. Export/import and/or use of cryptography software, or even communicating technical details about cryptography software, is illegal in some parts of the world. You are strongly advised to pay close attention to any export/import and/or use laws which apply to you when you import a release of Berkeley DB including cryptography to your country or re-distribute source code from it in any way. If this is a concern, we recommend downloading the NC (for non-crypto) versions of Berkeley DB product downloads because they do not include cryptography code.
Berkeley DB's header file db.h
and Microsoft's header file oledb.h
both define the symbol DBTYPE
. Unfortunately, changing either use of this symbol would break existing code.
The first and simplest solution to this problem is to organize your source code so that only one of these two header files is needed in any of your sources. In other words, separate the uses of Berkeley DB and the uses of Microsoft's OLE DB library so that they are not mixed in your code.
Then, just choose either db.h
or oledb.h
, but do not mix them in one source file.
If that is not possible, and you have to mix both headers, wrap one of the #include
lines as follows.
Find the line where oledb.h
is included in your source code. This may be in the automatically-generated stdafx.h
include file. Decide whether that header file is really needed. If it is, change the include line from this:
#include <oledb.h>
to this:
/* Work around DBTYPE name conflict with Berkeley DB */
#define DBTYPE MS_DBTYPE
#include <oledb.h>
#undef DBTYPE
Then if you need to use Microsoft's DBTYPE
, refer to it as MS_DBTYPE
. Alternatively, for C applications, you can wrap the include of db.h in a similar way.
You can not wrap db_cxx.h using this technique. If you are using the C++ interface to Berkeley DB, you need to with avoid mixing oledb.h with db_cxx.h or wrap the include of oledb.h as described above.
The Berkeley DB environment keeps memory for a fixed number of lockers, locks and lock objects -- so it is always possible to run out of these resources. The maximum amount of lock resources to be allocated is set when the database environment is created, so to change this number, you will need to increase the increase the number of lockers, locks and/or lock objects and re-create your environment. See the Configuring locking: sizing the system section of the Berkeley DB Reference Guide for more information.
The application is calling the Berkeley DB API incorrectly or configuring the database environment with insufficient resources.
The Berkeley DB library outputs a verbose error message whenever it is about to return a general-purpose error, or throw a non-specific exception. Whenever it is not clear why an application call into Berkeley DB is failing, the first step is always to review the verbose error messages, which will almost always explain the problem.
See the Run-time error information section of the Berkeley DB Reference Guide for more information.
It's also useful to know how Berkeley DB divides up the error name space: Except for the historic dbm, ndbm, and hsearch interfaces, Berkeley DB does not use the global variable errno
to return error values. The return values for all Berkeley DB functions are grouped into the following three categories:
ENOMEM
.
DB_NOTFOUND
when the key/data pair does not appear in the database; as opposed to the value of 0, which would be returned if the key/data pair were found in the database.
All values returned by Berkeley DB functions are less than 0 in order to avoid conflict with possible values of errno. Specifically, Berkeley DB reserves all values from -30,800 to -30,999 to itself as possible error values. There are a few Berkeley DB interfaces where it is possible for an application function to be called by a Berkeley DB function and subsequently fail with an application-specific return. Such failure returns will be passed back to the function that originally called a Berkeley DB interface. To avoid ambiguity about the cause of the error, error values separate from the Berkeley DB error name space should be used.
Finally, you can always get the message string that's associated with the error number that Berkeley DB returns from the db_strerror function. The db_strerror
function is a superset of the ANSI C X3.159-1989 (ANSI C) strerror(3)
function. If the error number error is greater than or equal to 0, then the string returned by the system function strerror(3)
is returned. If the error number is less than 0, an error string appropriate to the corresponding Berkeley DB library error is returned.</p>
Berkeley DB can continue to run when when out-of-disk-space errors occur, but it requires the application to be transaction protected. Applications which do not enclose update operations in transactions cannot recover from out-of-disk-space errors, and the result of running out of disk space may be database corruption.
Usually, what appears to be a corrupted database, is usually the result of two database handles not sharing an underlying database environment. See the Opening multiple databases in a single file section of the Berkeley DB Reference Guide for more information.
When a Berkeley DB application calls the database handle close method to discard a database handle, the dirty pages in the cache will written to the backing database file by default. To change this behavior, specify the DB_NOSYNC
flag to the Db.close
(or the noSync
flag to the Database.close
method when using the Java API); setting this flag will cause the handle close method to ignore dirty pages in the cache.
Many applications do not need to flush the dirty pages from the cache when the database handle close method is called. Applications using transactions or replication for durability don't need to flush dirty pages as the transactional mechanisms ensure that no data is ever lost. Further, there is never a requirement to flush the dirty pages from the cache until the database environment is about to be removed: processes can join and leave a database environment without flushing the dirty pages held in the cache, and only when the database environment will never be accessed again should dirty pages be flushed to the backing file.
The most common reason for this error in a Berkeley DB application is that a system call underlying a mutex configured by Berkeley DB is not available on the system, thus, the return of ENOSYS
, (which is the system error associated with the Function not implemented message).
Generally, this happens because the Berkeley DB library build was specifically configured to use POSIX mutexes, and POSIX mutexes aren't available on this system, or the library was configured on a different system where POSIX mutexes were available, and then the library was physically moved to a system where POSIX mutexes were not available.
This error happens occasionally on Linux systems, because some Linux systems have POSIX mutex support in the C library configuration, but not in the operating system, or the POSIX mutex support they have is only for intra-process mutexes, not inter-process mutexes.
To avoid this error, explicitly specify the mutex implementation DB should use, with the --with-mutex=MUTEX
configuration flag:
--with-mutex=MUTEX
To force Berkeley DB to use a specific mutex implementation,
configure with --with-mutex=MUTEX, where MUTEX is the mutex
implementation you want. For example,
--with-mutex=x86/gcc-assembly will configure Berkeley DB to use
the x86 GNU gcc compiler based test-and-set assembly mutexes.
This is rarely necessary and should be done only when the
default configuration selects the wrong mutex implementation. A
list of available mutex implementations can be found in the
distribution file dist/aclocal/mutex.ac
This generally happens when using uninitialized memory. It is the responsiblity of the application to zero out the DBT
objects before invoking the Berkeley DB API. Before using a DBT
, you must initialize all its elements to 0 and then set the ones you are using explicitly.
Another common explanation of this symptom is the application may be using Berkeley DB handles in a free-threaded manner, without specifying the DB_THREAD
flag to the DB->open
or DB_ENV->open
methods. Any time you are sharing a handle across multiple threads, you must specify DB_THREAD
when you open that handle.
Another reason for this symptom is the application is concurrently accessing the database, but not acquiring locks. The Berkeley DB Data Store product does no locking at all; the application must do its own serialization of access to the database to avoid corruption. The Berkeley DB Concurrent Data Store and Berkeley DB Transactional Data Store products do lock the database, but still require that locking be configured.
Yes. Databases can be moved between 32- and 64-bit machines, as well as between little- and big-endian machines. See the Selecting a byte order section of the Berkeley DB Reference Guide for more information.
We found that running with memory mapped files on Z/OS is problematic. The visibility of writes in the memory region requires a sync to allow other processes to view them. This greatly slows down performance. We recommend against using memory mapped files when using Z/OS.
A checkpoint doesn't block access to the Berkeley DB database environment, and threads of control can continue to read and write databases during checkpoint. However, the checkpoint potentially triggers a large amount of I/O which could slow other threads of control, and make it appear that access has been blocked.
You can use the DB_ENV->memp_trickle
method to spread out the I/O that checkpoint will need to perform (the DB_ENV->memp_trickle
method ensures a specified percent of the pages in the cache are kept clean). Alternatively, you can limit the number of sequential write operations scheduled by the DB library, using the DB_ENV->memp_set_max_write
method. The DB_ENV->memp_set_max_write
method affects all of the methods that flush the database cache (checkpoint, as well as other methods, for example, DB->sync
).
LSN stands for log sequence number. Sometimes when this happens you'll also see the message, transactional database environment cannot be recovered. Log files contain information about transactions, when you see this message it is likely that the application or some other process or systems anomoly may have removed some or all of the log files without properly resetting the database log sequence numbers (LSNs). Log files should never be removed unless explicitly authorized by the db_archive
utility or the DB_ENV->log_archive
method. Note that those interfaces will never authorize removal of all existing log files.
It may also be that an application has created a database file in one transactional environment and then moved it into another transactional environment. While it is possible to create databases in non-transactional environments (for example, when doing bulk database loads) and then move them into transactional environments, once a database has been used in a transactional environment, it cannot be moved to another environment without first resetting the database log sequence numbers. See the DB_ENV->lsn_reset
method documentation for more information.
There are a few potential common explanations for this kind of behavior:
DB_RMW
flag on your {{DB->get()}}} calls.
This error means the maximum number of active transactions configured for Berkeley DB has been reached. The Berkeley DB environment should be configured to support more active transactions. When all of the memory available in the database environment for transactions is in use, calls to being a transaction will fail until some active transactions complete. By default, the database environment is configured to support at least 20 active transactions. For more information see the Configuring transactions section of the Berkeley DB Reference Guide.
The DB_AUTO_COMMIT
flag does not apply to cursors. If you want transactions for cursor operations you must create and use an explicit transaction.
Berkeley DB works great with a SAN (and with any other filesystem type as far as we know), but if you attempt to access any filesystem from multiple machines, you are treating the filesystem as a shared, remote filesystem and this can cause problems for Berkeley DB. See the Remote filesystems section of the Berkeley DB Reference Guide for more information. There are two problems with shared/remote filesystems, mutexes and cache consistency. First, mutexes: For remote filesystems that do allow remote files to be mapped into process memory, database environment directories accessed via remote filesystems cannot be used simultaneously from multiple clients (that is, from multiple computers). No commercial remote filesystem of which we're aware supports coherent, distributed shared memory for remote-mounted files. As a result, different machines will see different versions of these shared region files, and the behavior is undefined. For example, if machine A opens a database environment on a remote filesystem, and machine B does the same, then machine A acquires a mutex backed in that remote filesystem, the mutex won't correctly serialize machine B. That means both machines are potentially modifying a single data structure at the same time, and any bad database thing you can imagine can happen as a result. Second caches:
Databases, log files, and temporary files may be placed on remote filesystems, as long as the remote filesystem fully supports standard POSIX filesystem semantics (although the application may incur a performance penalty for doing so). Further, read-only databases on remote filesystems can be accessed from multiple systems simultaneously. However, it is difficult (or impossible) for modifiable databases on remote filesystems to be accessed from multiple systems simultaneously. The reason is the Berkeley DB library caches modified database pages, and when those modified pages are written to the backing file is not entirely under application control. If two systems were to write database pages to the remote filesystem at the same time, database corruption could result. If a system were to write a database page back to the remote filesystem at the same time as another system read a page, a core dump in the reader could result. For example, if machine A reads page 5 of a database (and page 5 references page 6), then machine B writes page 6 of the database, and then machine A reads page 6 of the database, machine A has an inconsistent page 5 and page 6, which can lead to incorrect or inconsistent data being returned to the application, or even core dumps. The core dumps and inconsistent data are limited to the readers in this scenario, and some applications might choose to live with that. You can, of course, serialize access to the databases outside of Berkeley DB, but that would imply a pretty significant hit to the overall performance of the system. So Berkeley DB is not designed to fully support multi-system concurrent access to a database environment on a shared disk available either on a network filesystem or a SAN.
Berkeley DB wasn't designed to use raw disk partitions, for a few different reasons:
All that said, the one strong argument for porting to a raw partition is to avoid double buffering (where a copy of a Berkeley DB database page is held in both the DB cache and the operating system's buffer cache). Fortunately, modern operating systems allow you to configure I/O to copy directly to/from the DB cache, avoiding the OS buffer cache and double buffering. It would not be a lot of work to change Berkeley DB to create databases on a raw partition: simply replace the underlying open, read, write and lseek interface calls to work on a raw partition. However, making Berkeley DB fully functional in that environment would require a lot of work, in order to make the general administration of the database environment work as smoothly as it does now. That said, third-party researchers experimenting with Berkeley DB have done this. Their work is not available in any form, but serves as a proof point.
This is usually the result of using integer keys on little-endian architectures such as the x86. Berkeley DB's default key comparison function, the code that is used to order the keys in your btree, treats the data in the DBT
which you know to be an integer as a byte strings. As it turns out, little-endian integers don't sort well when compared as though they were strings. For example, take the numbers 254 through 257. Their byte patterns on a little-endian system are:
254 fe 0 0 0
255 ff 0 0 0
256 0 1 0 0
257 1 1 0 0
If you treat them as strings, then they sort badly:
256
257
254
255
On a big-endian system, their byte patterns are:
254 0 0 0 fe
255 0 0 0 ff
256 0 0 1 1
257 0 0 1 1
and so, even when compared as strings the keys will sort nicely. Which means, if you use steadily increasing integers as keys on a big-endian system Berkeley DB behaves well and you get compact trees, but on a little-endian system Berkeley DB produces much less compact trees. To avoid this problem, you may want to convert the keys to flat text or big-endian representations, or provide your own Btree comparison function using the DB->set_bt_compare
method.
Replication Manager uses IPv6 addresses whenever possible. A dual stack machine is a machine that supports use of both IPv6 and IPv4. It is common practice to define a host name that maps to both IPv6 and IPv4 addresses on a dual stack machine. When such a host name is used to specify a Replication Manager site, Replication Manager always tries IPv6 addresses first.
In order to use IPv4 connections, you must specify Replication Manager sites on dual stack machines in one of the following ways: use a host name that only maps to IPv4 addresses or use an IPv4 numeric address in dot-decimal notation.
Replication Manager introduced Group Membership in the Berkeley DB 11.2.5.2 release. This feature improves Replication Manager's ability to manage various replication activities based on the number of sites in the replication group.
If you are a Replication Manager user upgrading from a version of Berkeley DB prior to 11.2.5.2 to Berkeley DB 11.2.5.2 or later, you need to follow some additional upgrade steps to start using Group Membership. These steps are described in Upgrading groups.
Berkeley DB's SQL API is the SQL processing top half of SQLite layered on top of the storage engine of Berkeley DB. This combination of Berkeley DB and SQLite provides a SQL command line utility called dbsql
(a functional equivalent of the sqlite3
command line utility), third party libraries (including JDBC and ODBC), and the SQLite version 3 C/C++ API. This feature is enabled by passing the --enable-sql
argument to the configure
script before you build the library and tools from the Berkeley DB package.
Many, including:
Many, including:
You have a number of options to consider when setting up Berkeley DB's source code for a build. This is done using the configure
script in the dist
directory. If you were on a UNIX-like system you can see the options by doing:
$ cd db
$ cd build_unix
$ ../dist/configure --help
In that output you'll see:
--enable-sql Build the SQL API.
--enable-sql_compat Build a drop-in replacement sqlite3 library.
--enable-jdbc Build BDB SQL JDBC library.
--enable-amalgamation Build a SQL amalgamation instead of building files
separately.
So to build a drop in replacement do:
$ ../dist/configure --enable-sql --enable-sql_compat
First, recall that the Berkeley DB SQL API is essentially identical to SQLite. The products [do differ in some significan ways http://www.oracle.com/technetwork/database/berkeleydb/bdb-sqlite-comparison-wp-176431.pdf], but it's best to first understand and use [SQLite http://sqlite.org] and then find out what benefits there are to using BDB's SQL API. Alternatively there are many tutorials to help you get started with the Berkeley DB SQL Interface. Remember to build with --enable-sql
passed to the configure
script to generate the SQL library and command line tool dbsql
. If you don't build the drop-in replacement remember that where a tutorial suggests running the sqlite3
command line tool, you'll run the Berkeley DB dbsql
tool instead.
Most platforms will be supported. Our developers have tested on:
Systems with support for POSIX should work. Berkeley DB is engineered to use as few operating system calls as possible, this makes it is highly portable.
Run the Berkeley DB configure utility as normal, adding the --enable-sql
flag. For example:
download db-5.0.XX.tar.gz
$ tar xzvf db-5.0.XX.tar.gz
$ cd db-5.0.XX/build_unix
$ ../dist/configure --enable-sql
$ make
Once complete, you should then have a library called libdb_sql-5.0.la
and a command line tool called dbsql
that can create and manipulate SQL databases in the following manner:
$ dbsql test.db
Berkeley DB SQL interface version 11.2.5.1.XX
Enter .help for instructions
Enter SQL statements terminated with a ;
dbsql> create table t(a integer, b string);
dbsql> insert into t values (1, 'one');
dbsql> insert into t values (2, 'two');
dbsql> select * from t;
1|one
2|two
Yes, by specifying the --enable-sql_compat
flag to Berkeley DB's configure script. That will create an additional library called libsqlite3.la
and an additional binary called sqlite3
, which have an identical interface to SQLite.
Open the Berkeley DB solution in Visual Studio and build the db_sql_shell
project. That will produce a binary called dbsql.exe
in the directory Win32/{Debug|Release}/
.
In addition to the in addition to the SQLite-specific compile-time flags Berkeley DB's SQL API can be further tailored with the following:
SQL92, apart from these exceptions.
There are no differences between the Berkeley DB's SQL API and the SQLite API related to SQL data types. The code to handle data types in Berkeley DB is identical to the code in SQLite.
First, take a minute to read the SQLite documentation on data types. SQL used to access statically typed databases will be compatible with Berkeley DB.
Yes. The application can generate and execute SQL statements at runtime if desired.
Yes, SQLite has support for prepared statements via the C/C++ API.
The SQLite alternative to PL/SQL is the native C/C++ interface. As is common with SQLite, there is 3rd Party support for PL/SQL which may be a viable alternative for your application.
Yes, conditional statements are fully supported.
No, though cursor semantics are available via the C/C++ APIs.
Berkeley DB library is thread safe, the SQL API uses TDS (transactional data store), you are free to use any variety of threads (BDB is thread agnostic) or multiple processes accessing the database concurrently. Berkeley DB will manage locking, serialization, and other issues for you. You'll want to learn about thread safety in SQLite too.
Yes, Berkeley DB automatically runs each command in its own transaction, and if the command does not fail, its changes are automatically committed. This mode of operation (implicit transactions) is referred to as autocommit mode. Using explicit transactions may improve system efficiency.
Most tools available for SQLite will work with the Berkeley DB application.
For information on other tools that can be used with the SQL interface, see the administration chapter of the Berkeley DB SQL API documentation.
Yes, there is a command line tool called dbsql
, which provides a SQL Interface from the command line. If Berkeley DB is configured with the --enable-sql_compat
flag, another copy of the command line tool will be built, with the same functionality, called sqlite3
.
Yes, the built-in .dump
command will produce SQL that can be executed to recreate a database.
There are many SQLite database management tools available. Of the list of tools known to work with SQLite one probably satisfies your particular requirements. It is also possible to use the SQLite command line SQL Interpreter to create tables, the command line can be used from a script.
Yes, there is a consistency checking tool built in. The check is accessed using a PRAGMA integrity_check
command. See the pragma page for more information.
This http://www.sqlite.org/datatype3.html">page explains: TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16-LE).
It is possible to store S-JIS directly, but it requires implementing some APIs so that SQLite can interpret the character set. UTF-8 encoding is preferred. Storing Shift-JIS directly, without converting to UTF-8, appears possible.
Please read the SQLite data type documentation.
See data types and language expression documentation on the SQLite site. Full search, partial match (LIKE
, GLOB
), and custom regular expressions are supported on all column types.
Yes. See documentation on collation sequences.
Because constraints are implemented in the SQLite code they are identical to SQLite's constraints. Primary keys normally imply a UNIQUE
constraint, except for integer primary keys. Unique key constraints are supported. Foreign key constraints are currently not supported (the statements will be parsed, but not enforced).
NULL values are supported, they sort before all other items in the table (including other NULL values). So there is no defined order amongst NULL VARCHAR fields.
This depends on the page size, the key size (are some values in each comma separated row the key?), page fill factor, and some minimal amount of meta-data overhead. If compression is used it could be smaller than 256KiB depending on the data and the compression algorithm. Berkeley DB will use more than 256KiB because there is some overhead in indexing the keys + some bytes of per page overhead. The index overhead is dependent on the size of the key, so difficult to estimate. For example, if the keys are small, then the index overhead will be small. Every DB adds some overhead for indexing, page header etc.
Transactions created using BEGIN...COMMIT
do not nest. For nested transactions, use the SAVEPOINT
and RELEASE
commands. This is identical to the behavior of SQLite.
Access control (authentication, user priviliges) is implemented at an application level.
Yes, it is possible to have multiple users connect to a database concurrently. There is no authentication in SQLite (see Q/A above), in this answer we're using the term user to mean thread or process.
Stored procedures are not supported by SQLite, and so they are not supported in Berkeley DB's SQL API either.
Yes, triggers are supported, but there are some unsupported uses.
Yes, transactions are supported, with the SQLite semantics, as described here.
Yes, backup is supported, via the standard Berkeley DB backup procedure.
Yes, consistency is guaranteed, unless a database is configured to disable the constraint.
If the filename is :memory:
, then a private, temporary in-memory database is created for the connection.
Currently, there is no support for pre-empting a low-priority operation.
Yes, all such issues are reported as error codes returned from API calls. The SQLite PRAGMA integrity_check
command can be used to explicitly validate a database.
Raw disk access is not currently supported, nor are there plans to support this functionality in the future.
SQLite has support for ALTER TABLE
, but it is limited. This is something that future versions of SQLite may change this.
The programming interface (API) and SQL language supported are identical: Berkeley DB uses that part of SQLite without any changes. Similarly for the special commands understood by the command line tool. However, the different storage architecture (and time available for the release) has meant that there are some caveats about 100% compatibility:
No, Berkeley DB does not include a complete copy of SQLite's code, we've taken out the btree
files. In particular, all of the code relating to manipulating files has been replaced by the Berkeley DB storage engine. You will need to migrate the schema and data using the sqlite3
command line interface to .dump
and then the Berkeley DB dbsql
command line to .load
the data and schema from the dump file.
Use the sqlite3
command tool that is part of SQLite and run this:
$ sqlite3 my.db '.dump' | dbsql new.db
BEGIN IMMEDIATE/EXCLUSIVE
do in Berkeley DB?
These special transaction modes are used in SQLite to avoid deadlock. Internally, SQLite has the notion of read-only vs update transactions. These keywords apply to update transactions, and fully understanding them requires understanding SQLite locking. In Berkeley DB, these keywords are mostly ignored. That is, they are not required to avoid deadlock (nor do they prevent deadlocks, but such deadlocks are automatically detected by Berkeley DB). The effect of using either keyword is that the transaction starts as an update transaction, which causes exclusive locking for reads (similar to SELECT FOR UPDATE
in other RDBMSs). This can reduce the frequency of deadlocks in some applications.
Beginning in 5.2, BEGIN EXCLUSIVE
will create a transaction that will block new transactions from starting, and block existing transaction from making forward progress, until the exclusive transaction is committed or aborted.
In Berkeley DB, PRAGMA synchronous
has a different meaning to SQLite. In SQLite, with levels lower than FULL
, databases may be corrupted after a failure. In Berkeley DB, databases can always be recovered to a consistent state, because write-ahead logging semantics are always enforced on the Berkeley DB log. So the synchronous
setting can improve throughput in Berkeley DB without risking corruption. The synchronous=ON
level in Berkeley DB is equivalent to the DB_TXN_WRITENOSYNC
flag and implies that transactions committed before a system crash (such as a hard reboot or power loss) may be rolled back on recovery. Application crashes do not cause committed transactions to be rolled back at this level. The synchronous=OFF
level is equivalent to the DB_TXN_NOSYNC
flag and implies that committed transactions may be rolled back after either an application or a system crash.
Yes - there is an ADO.NET package for Berkeley DB. It is available from the Berkeley DB Download page, and includes documentation. If you need help ask a question on our forums.
No - you don't need to be concerned. The warning appears because we auto-generate the build files outside of Visual Studio. There is nothing harmful in our files.
The exact warning message is: "Security warning for System.Data.SQLite.2008"
These are the same thing. The ADO.NET package provides an implementation of System.Data.SQLite for .NET.
Please contact us if you need to use fts1 and fts2.
Cache size 10MiB by default, minimum 100KiB. Log buffer size is 32KiB. Typically an additional 100KiB is used for other purposes. The minimum total size is approximately 1MiB.
Berkeley DB configures a default page size based on the underlying file systems block size. See the documentation about page size tuning in Berkeley DB for more information.
The number of tables open is generally only limited by the number of file handles that can be opened.
The table size is generally limited by the maximum file size possible on the file system.
There is no practical limit. It is possible to store the number of records that can be indexed in a signed 64-bit value.
There is no practical constraint. The maximum length of a string or blob field is 1 billion bytes.
The SQLite optimizer is not particularly smart: it has some heuristics that boil down to using an index whenever one is available. There is some modeling of costs of queries, and there optional support for an analyze command that maintains statistics, but they are not very sophisticated. You can always find more detail on the internal workings of SQLite on its website as well as in this SQLite optimization FAQ, though some of it is out of date.
There are several sources of file size overhead in the Berkeley DB storage engine:
It is impossible to say exactly what impact these factors will have on database file size: the worst case would be with many indices and small records. With larger records and fewer indices, the file size may be in the same ballpark as SQLite.
When you create a table in SQL, a primary subdatabase is created in the Berkeley DB file. This primary database has integer keys that are usually allocated by SQLite and can be referred to from SQL by the implicit column name rowid
. Each index that is declared in SQL creates an additional subdatabase, containing keys that include an encoding of the fields from the SQL columns making up the index, along with the row ID of the matching row in the primary. The Berkeley DB data
part of these records is always empty: SQLite only ever sets or uses the keys. One special case is worth mentioning: applications that want an integer primary key for a table should declare the table as:
create table t(id integer primary key, ...)
This is handled by the SQLite parser, making the id
an alias for the row ID. In other words, this avoids the maintenance of a secondary index, and the associated lookup cost at runtime. No other syntax, including creating an integer primary key
index as a separate statement, will be handled in this special way. Note that Berkeley DB's built-in support for secondary indices and foreign keys is not used by the SQL Interface: indices are maintained by the SQLite query processor.
A file refers to an entire SQL database (tables, indexes, everything), so SQLite usually does database-wide locking. The locking situation is more complex when SQLite is used in shared cache mode, where some operations lock a table rather than the whole file, but only relative to threads in the same process sharing the cache.
Locking has a significant impact on some queries: we have seen up to 30% of the runtime for some queries connected with locking (and latching). While scans do lock each leaf page in a table, they generally map to a bulk get, and the locking cost is often not significant. The most costly queries are ones that involve many random lookups, since each individual lookup acquires page locks in Berkeley DB. In particular, queries that use an index, but have moderate to high selectivity will typically perform worst with Berkeley DB: the relevant rows are identified quickly with an index scan, but looking up each row in the primary has a high overhead. Workarounds are standard RDBMS optimization techniques: avoid using an index (scan the primary), or to create a covering index (one which contains all columns of interest), so the primary does not need to be accessed.
DB_TXN_NOSYNC
DB_TXN_WRITE_NOSYNC
FULL is the default setting, if no pragma is used.
SQLite implements the VACUUM
command as a database dump followed by a complete reload from that dump. It is an expensive operation, locking the entire database for the duration of the operation. It is also an all or nothing operation. Either it works, or it fails and you have to try again sometime. When SQLite finishes, the database is frequently smaller in size (file size is smaller) and the btree is better organized (shallower) than before due to in-order key insertion of the data from the dump file. SQLite, when it works and when you can afford locking everyone out of the database, does a good job of VACUUM. Berkeley DB approaches this in a completely different way. For many releases now Berkeley DB's B-Tree implementation has had the ability to compact while other oprations are in-flight. Compacting is a process wherein the B-Tree nodes are examined and, when less than optimal, they are re-organized (reverse split, etc.). The more shallow your B-Tree, the fewer lookups required to find the data at a leaf node. Berkeley DB can compact sections of the tree, or the whole tree at once. For 7x24x365 (five-nines) operation this is critical. The BDB version of compact won't adversly impact ongoing database operations whereas SQLite's approach does. But compaction doesn't address empty sections of the database (segments of the database file where deleted data once lived). Berkeley DB also supports compression of database files by moving data within the file, then truncating the file returning that space to the filesystem. As of release 5.1 of Berkeley DB, the VACUUM command will compact and compress the database file(s). This operation takes more time than the dump/load approach of SQLite because it is doing more work to allow for the database to remain operational. We believe this is the right trade-off, but if you disagree you can always dump/load the database in your code.
Yes, the btree implementations are fairly similar at this level. SQLite uses a different algorithm for keeping its tree balanced, but space from deleted rows on a page can be reused, and once all rows are deleted from a page, the page is put on a free list and can be recycled. In Berkeley DB, if it happens that some pages at the end of the file become free, the file is automatically truncated.
Automatic deadlock detection is enabled, it uses the default deadlock resolution algorithm. See the [" hre="http://download.oracle.com/docs/cd/E17076_02/html/api_reference/C/envset_lk_detect.html set_lk_detect documentation] for further information.
By default, log files are automatically removed when all the information they contain has been synced to the database file. That means that incremental backups need special care in order to work. Automatic log file removal can be disabled at compile time by specifying the BDBSQL_OMIT_LOG_REMOVE
preprocessor flag.
None specifically, but there are many resources available for performance tuning SQLite applications/databases.
Yes. If you intend to connect these processes at the same time as other access to the database, you should use the DB_REGISTER
flag. This means that using the Berkeley DB utilities requires additional care because they generally don't set this flag.
SQLite refers to tables with an ID number (in SQLite that's the root page of the btree for that table), whereas Berkeley DB refers to subdatabases by name. The mapping is simply:
sprintf(table_name, table, table_id);
The IDs are allocated so that tables ordinary tables always get an odd number and indices get an even number. You can find the ID for a SQL table called t1
with the following query:
select rootpage from sqlite_master where name=t1;
This can be used, for example, to get statistics about a particular table using the db_stat
utility with the -s
flag.
DB_CONFIG
file to override default settings?
Yes, create the journal directory and DB_CONFIG
file before creating the database. Alternative, when the database file is not in use, create a DB_CONFIG
file and run the db_recover
utility manually. Note that before running any Berkeley DB utility, the DB_CONFIG
file for SQL databases should contain the line:
add_data_dir ..
:memory:
databases? Do they use the Berkeley DB cache internally?
Temporary tables don't live in a file on disk, and they have in-memory logs that allow transactions and savepoints to work as expected from SQL. There is no durability, so no recovery after a crash. Other than that, no, there is nothing special. A :memory:
database consists entirely of temporary tables. They use an internal cache, allocated when the first temporary table is created.
The SQLite C++ API returns error codes, rather than using exception handling.
SQLITE_BUSY
easily?You can register a busy callback handler by SQLite's API:
int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
That makes it easy to deal with SQLITE_BUSY
event automatically. Otherwise, you have to check the return code and retry manually. Alternatively, you can use:
int sqlite3_busy_timeout(sqlite3*, int ms);
to set the timeout threshold. How can I iterate through a result set?
sqlite_exec()
), you can setup a callback function for the 3rd argument of sqlite_exec()
to iterate result.
sqlite3_column_*()
functions to fetch the result of current statement step.
sqlite3_get_table()
to fetch results into memory data structure directly, but that is subject to the size of result set and available memory of system.
sqlite3_prepare()
, sqlite3_prepare_v2()
, sqlite3_prepare16()
and sqlite3_prepare16_v2()
?
The sqlite3_prepare()
and sqlite3_prepare_v2()
interfaces use UTF-8, and sqlite3_prepare16()
and sqlite3_prepare16_v2()
use UTF-16. The sqlite3_prepare_v2()
and sqlite3_prepare16_v2()
interfaces are recommended for all new programs. The two older interfaces are retained for backwards compatibility, but their use is discouraged. More details are in the SQLite docs on prepare.
Yes, when you create a table in Berkeley DB 11gR2, you do not need to specify a primary key. In this case, Berkeley DB 11gR2 will create an implicit integer row ID
column as the primary key, so if you specify a non-integer primary key, there will be a second table that maps the primary key to the row ID. There are two Berkeley DB tables in that case:
You can try one of following ways:
explain
before SQL statements to get the query plan(VDBE format).
dtrace
on Solaris or Mac OS/X
In the SQL command line mode, command select * from sqlite_master;
will list these information. Please refer to the SQLite tutorial for more supported SQL statements.
Yes, Berkeley DB includes an open source JDBC driver.
Currently, the JDBC driver doesn't support below properties:
prepareCall
savePoint(setSavepoint/rollback/releaseSavepoint)
prepareStatement()
is conditionally supported only when the resultSetType
is one of FORWARD_ONLY
or SCROLL_INSENSITIVE
or SCROLL_SENSITIVE
and the resultSetConcurrency
is one of CONCUR_REQD_ONLY
or CONCUR_UPDATABLE
.
getParameterMetaData
Yes, Berkeley DB includes an open source ODBC driver.
Yes, this is supported by sqliteodbc using sqlite3_interrupt.
Yes, supported by sqliteodbc using sqlite3_interrupt.
The Visual Studio 2008 project files will by default build for Windows Mobile 6.5.3 Professional. If you want to build for other platforms such as Windows Mobile 6.0, 6.1, or 6.5, you need to follow the steps in the Windows CE build documentation.
Transaction snapshots are not supported in 5.0 or 5.1. Beginning in 5.2, transaction snapshots can be enabled using the pragmas PRAGMA multiversion=on|off
and PRAGMA snapshot_isolation=on|off
. Using DB_CONFIG
to set DB_MULTIVERSION
and DB_TXN_SNAPSHOT
will not work correctly in any version of the SQL API.
When you use the following pragma to turn off replication:
pragma replication=OFF;
its effect is delayed until all database connections have been disconnected and Berkeley DB recovery has been run on the database. Recovery should be run using the Berkeley DB db_recover utility with the following command:
db_recover -h <database name>-journal
Recovery is run on the journal directory that Berkeley DB creates alongside your database. For example, the database test.db
would have the journal directory test.db-journal
.
Please note that any changes you make at a site where replication is turned off are likely to disappear if you turn replication back on. The effect of turning replication back on is also delayed until all database connections have been disconnected and you reopen the database. Upon reopening the database, the site synchronizes with the rest of the replication group.
This is not a bug of BDB. It's caused by a fix in the ext4 fsync code with this patch from 2.6.32. This fix is required for safe behavior with volatile write caches. The high performance number before is fictitious. With 2.6.32 released with ext4 defaulting to proper behavior on fsync(),we might finally be able to use regular drives with their caches turned on safely, taking advantage of the cache for other writes while doing the right thing with the database writes.
In RHEL 5, a new kernel parameter was added that specifies whether or not memory-mapped file pages should be flushed to disk by update while the memory map is active. Be default BDB uses memory-mapped files for all its environment files. You may need to set flush_mmap_pages to zero to see the behavior that you saw in RHEL 4.
When a user does a large number of database put operations in a short time on certain Windows x64 OS platforms (notably Vista, Windows Server 2003, and Windows Server 2008), the working set size of the system file cache will grow to meet this demand. Over time, the available memory can be exhausted, and the system can run painfully slow. This is a bug in the Windows OS, and not in BDB. (For reference, including a link to a list of affected platforms, see knowledge_note). As a workaround, you can turn off buffered I/O in Windows by specifying the DB_DIRECT_DB flag to the environment. This is the equivalent of calling CreateFile with specifying FILE_FLAG_NO_BUFFERING and causes all I/O to go straight to the disk instead of memory. A second option is to use the SetSystemFileCacheSize API provided by Windows to restrict the consumption of physical memory.