Мэтью Сеттер — профессиональный технический писатель и страстный разработчик веб-приложений. Он также является основателем Malt Blue , сообщества профессионалов по разработке веб-приложений на PHP и специалистов по разработке облачных решений PHP — изучающих разработку облачных вычислений через призму PHP. Вы можете связаться с ним в Twitter , Facebook , LinkedIn или Google+ в любое время.
Если вы давний PHP-разработчик, энтузиаст с открытым исходным кодом или выродок любого уровня, то вы слышали о том, что можно назвать золотой квадриологией реляционных баз данных для разработки веб-приложений: MySQL, PostgresSQL, Microsoft SQL Server, и Oracle.
С их доминированием на рынке вы, возможно, не слышали об альтернативах большой четверке. И вы могли бы легко быть прощены за то, что не искали в другом месте. Но, несмотря на их относительные достоинства, впечатляющие родословные, коммерческую поддержку и большие сообщества, они едва ли не единственные шоу в городе.
В наше время существует множество доступных нам вариантов. В этой серии из трех частей я расскажу вам о пяти альтернативных базах данных, о которых вы, возможно, слышали или не слышали. В этом я объясню:
* Почему они могут быть ценным дополнением к вашему набору средств разработки программного обеспечения
* Где их лучше всего применять
* Как начать работу с ними
Принимаете ли вы участие во встраиваемой разработке, OLTP, OLAP, масштабируемой масштабируемости и хранении или в простых приложениях, поддерживаемых базой данных, вы не собираетесь уходить с той же точки зрения, которая была у вас до того, как вы начали читать эти сообщения. Итак, без дальнейших церемоний, давайте начнем с взгляда на ветерана Интернета: Беркли DB .
Berkeley DB
Berkeley DB существует довольно давно, еще до появления всемирной паутины, какой мы ее знаем сегодня. Еще в 1991 году Калифорнийский университет переходил с BSD v4.3 на v4.4 и хотел распространять версию UNIX, в которой не было проприетарного кода AT & T. Беркли DB должен был заменить существующие пакеты hsearch и dbm / ndbm.
Margo Selzer and Mike Olson created a library toolkit that provided a very robust and high performing key/datastore solution. Since then, the code has been used in a variety of products, including the 389 Directory Server (formerly the Netscape LDAP Server), Asterisk PBX, Postfix, Sendmail, SpamAssassin, and Subversion. Each version became increasingly sophisticated, without adding too much complexity.
They include such features as:
* Concurrent data access
* Transaction logging and recovery
* High availability capabilities
* Write-ahead logging
* Checkpoints
In addition, Berkeley DB adds the following features:
* Records and keys can be up to 4GB in length
* A single database can be up to 256 petabytes
* Supports fast data access (keyed and sequential)
* Supports ACID transactions, fine grained locking, hot backups and replication
* Available under Sleepycat Public License or a proprietary license
* Multiple language bindings, including C/C++, Java, C#, .NET, Perl, Python, Ruby, and PHP
What’s more, it’s been available for years in standard Linux and BSD package repositories. You’ve likely already been in contact with it, or only a step or two away. The reason you might not have heard of it is because it’s not quite a database – at least in the same vein as, say, Oracle, SQLServer or MySQL. Whereas these are more of the traditional RDBMS variety, Berkeley DB is a library and consequently takes a different approach.
With Berkeley DB, you cannot access the database over a network via TCP. Instead, you have to make in process API calls and you don’t have a table, row, column structure either.
Where as traditional RDBMS’ place clear constraints on how you’ll create the structure of your datastore and how it can be optimized, Berkeley DB leaves this wide open. Instead, you can stipulate just how you want the data to be stored, as it suits the needs of your application – similar to the new breed of NoSQL databases including mongoDB, Hadoop and CouchDB.
What’s It Good For?
So what can you use Berkeley DB for? Well, the answer is just about anything. Maybe you’re looking for:
• An embedded database
• An in-memory database
• A massive key/value store
• A datastore that’s both ultra-fast and ultra-scalable
No matter which of these or a combination of these your looking for, Berkeley DB is up to the task.
How Do You Use It?
But enough talking. Let’s install Berkeley DB locally and have a look at the code so you can see just how easy it is to use.
If you’re on Windows, refer to the Google Code project tutorial. If you’re on Linux or a BSD variant, it’s likely to be in the package repositories. If you want to install it from source, grab a copy of the latest version and run a standard configure, make and make install similar to that below.
./configure make make install
After that, you need to install or configure the dba extension for PHP. While the DBA functions list doesn’t have many functions available, you shouldn’t underestimate the functionally it can provide.
Let’s look at a simple example:
<?php define('DATABASE_NAME', "/tmp/test.db"); define('RECORD_KEY', "key"); define('RECORD_VALUE', "This is another example!"); $dbID = dba_open(DATABASE_NAME, "n", "db4"); if (!$dbID) { echo "dba_open failed\n"; exit; } // replace/insert a value dba_replace(RECORD_KEY, RECORD_VALUE, $dbID); // display the value if it exists and delete afterwards if (dba_exists(RECORD_KEY, $dbID)) { echo dba_fetch(RECORD_KEY, $dbID); dba_delete(RECORD_KEY, $dbID); } dba_close($dbID);
In the example above, we’ve defined a set of variables which store the name of our database, the record key and the record value. We then open a db4 version database with create, truncate and read-write access.
Let’s do a quick check to see if the database opened successfully and then set about adding the data to the database. Though the command is named dba_replace, this command does one of two things.
1. If the record exists, its value is replaced with the new value.
2. If it doesn’t, then it’s created with the value provided.
Nice and simple.
Following this, we check if the record exists, fetch it from the database, print it, and delete it afterwards. After all the work is done, we close the connection. Now let’s have a look at a slightly less trivial example.
A Slightly Less Trivial Example
Let’s say that we’re creating a simple in-memory phonebook. The key will be the user’s username and the value will be the full contact details of the user in JSON format.
class simpleAddressBook { // the database filename const DATABASE_NAME = "/tmp/address-book.db"; protected $_dbhndl = null; public function __construct($dbname = null) { if (!empty($dbname)) { $this->_dbhndl = dba_open($dbname, "n", "db4"); } else { $this->_dbhndl = dba_open(self::DATABASE_NAME, "n", "db4"); } if (!$this->_dbhndl) { throw new Exception("dba_open failed"); } } public function __destruct() { dba_close($this->_dbhndl); } public function persist($username, array $userData = array()) { if (!empty($username) && !empty($userData)) { return dba_replace($username, json_encode($userData), $this->_dbhndl); } return FALSE; } public function remove($username) { if (!empty($username) && dba_exists($username, $this->_dbhndl)) { return dba_delete($username, $this->_dbhndl); } return FALSE; } public function find($username) { if (!empty($username) && dba_exists($username, $this->_dbhndl)) { return json_decode(dba_fetch($username, $this->_dbhndl), TRUE); } return FALSE; } } $ab = new simpleAddressBook(); $username = "settermjd"; if ($userRecord = $ab->find($username) !== FALSE) { print_r($userRecord); } else { printf("User [%s] was not found<br />", $username); } $recordItem = array( 'name' => array( 'first' => 'Matthew', 'last' => 'Setter' ), 'email' => '[email protected]', 'url' => 'http://www.maltblue.com', 'phone' => '+44 12345 67890', ); if ($ab->persist($username, $recordItem)) { print "User stored successfully<br />"; } if (($userRecord = $ab->find($username)) !== FALSE) { print_r($userRecord); } else { printf("User [%s] was not found<br />", $username); }
Have a look at address-book.php. You can see that there is a class called simpleAddressBook. It has three functions: persist, remove and find. It also implements a constructor and destructor for opening and closing the database connection.
Following the class, we then interact with the address book by checking if the user record exists with the given username, create the record as a simple array, pass it to the persist function, and JSON encodes it and persists it in the database. Then we search for the record and display it if it’s found – which results in retrieving it – JSON decodes it back to the original array value and prints it on the screen.
As you can see, though there aren’t many functions available, we do have a lot of flexibility in what we can do with Berkeley DB. This post has only touched the surface of what’s possible. But I hope you can see how much power it has and how flexible it is to work with.
Winding Up
I hope you’ve enjoyed this first part of the series. In the next installment, I’ll be looking at Firebird, another old hand of the database world and newcomer Gladius DB, a database written in pure PHP and flat files. Until then, let me know what you think of Berkeley DB. Do you see a use for it in your applications?
Want to Learn More?
If you’d like more information about Berkeley DB, check out the following links:
* http://www.aosabook.org/en/bdb.html
* http://en.wikipedia.org/wiki/Berkeley_DB
* http://www.dolcevie.com/anton/docs/dr-dobbs-article.pdf
* http://www.stanford.edu/class/cs276a/projects/docs/berkeleydb/reftoc.html