in reply to Basic Database?

BerkeleyDB supports transactions and locking. You can also have non-unique keys. And, as others have suggested, you can use something like Storable to serialize the contents of the hashes you store if you need to.

Joins (though the underlying Sleepycat BerkeleyDB supports them) are not yet supported (though the manpage says that support is in progress). However, you could use the fine-grained locking and multiple tables to do joins manually.