首页 > 数据库 > > Berkeley DB的锁占用困惑?
Berkeley DB的锁是基于数据页(Page)为单位的,允许多个事务并发执行。在数据库外人为增加的队列、文件锁等行为,相当于加了一把全局锁,对数据库的并发性能有影响。一般情况下不建议这样做。
此外,对于并发读写数据库,还需要充分考虑和避免死锁情况。参考:
http://docs.oracle.com/cd/E17076_03/html/gsg_txn/C/blocking_deadlocks.html#deadlocks以下是对Berkeley DB锁系统防止写请求饿死的简要原理描述,实际实现涉及到很多细致的优化实现,会比原理描述复杂。
==================
数据库系统的性能至关重要,为了减轻锁粒度、提高并发性能,其内部锁系统设计相当复杂精巧。以Berkeley DB为例,锁系统中包括锁(Lock)、锁持有者(Locker)和被锁对象(Object)。可简单地认为锁持有者对应于读写事务,被锁对象对应于数据页。
Berkeley DB设计文档(src/lock/Design)指明:内部锁系统,对于被锁对象(Object),维护着holders和waiters两个链表。
OBJECT -----------------------
HASH | |
----|------------- |
________ _______ | | ________ | |
| |-->| O1 |--|---|-->| O2 | | |
|_______| |_____| | | |______| V |
| | W H--->L1->L2 W H--->L5 | holders
|_______| | | | | V
| | ------->L3 \ ------->L6------>L7 waiters
|_______| / \ \
. . / \ \
. . | \ \
. . | \ -----------
|_______| | -------------- |
| | ____|____ ___|_____ _|______
|_______| | | | | | |
| | | LID1 | | LID2 | | LID3 |
|_______| |_______| |_______| |______|
^ ^ ^
| | |
___|________________________|________|___
LOCKER | | | | | | | | |
HASH | | | | | | | | |
| | | | | | | | |
|____|____|____|____|____|____|____|____|
* Figure out if we can grant this lock or if it should wait.
* By default, we can grant the new lock if it does not conflict with
* anyone on the holders list OR anyone on the waiters list.
* The reason that we don't grant if there's a conflict is that
* this can lead to starvation (a writer waiting on a popularly
* read item will never be granted)... src/lock/lock.c中的注释指出,为了防止饿死,所申请的锁必须与现有的holders和waiters都不冲突,才能授予(成为holder)。否则将会被加到waiters中。
举例说明:对于某数据页面,目前holders中有10个读锁。写请求到达时,由于写锁与读锁冲突,申请的写锁会被加到waiters列表中。后续如果有新的读请求到达,此时waiters列表中已经有与之冲突的写锁占据,所以该读锁无法即时成为holder,必须加到waiters中等待写锁被释放。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69999831/viewspace-3144967/ ,如需转载,请注明出处,否则将追究法律责任。