Application Defined Page Cache
应用程序定义的页面缓存。
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
struct sqlite3_pcache_methods2 {
int iVersion;
void *pArg;
int (*xInit)(void*);
void (*xShutdown)(void*);
sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
int (*xPagecount)(sqlite3_pcache*);
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
unsigned oldKey, unsigned newKey);
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
void (*xDestroy)(sqlite3_pcache*);
void (*xShrink)(sqlite3_pcache*);
};
sqlite3_config(SQLITE_CONFIG_PCACHE2,...)接口可以通过传入 sqlite3_pcache_methods2 结构的实例来注册备用页面缓存实现。在许多应用程序中,大部分由 SQLite 分配的堆内存都用于页面缓存。通过使用此 API 实现自定义页面缓存,应用程序可以更好地控制 SQLite 消耗的内存量,分配和释放内存的方式以及用于准确确定数据库文件的哪些部分被缓存的策略以及多长时间。
备用页面缓存机制是一种极端措施,只需要最苛刻的应用程序。内建页面缓存推荐用于大多数用途。
在调用 sqlite3_config 时,sqlite3_pcache_methods2 结构的内容被 SQLite 复制到内部缓冲区。因此,应用程序可能会在调用 sqlite3_config()返回后放弃参数。
每次对 sqlite3_initialize()进行有效调用时,都会调用一次 xInit()方法(在进程的整个生命周期中通常只调用一次)。xInit()方法传递了 sqlite3_pcache_methods2.pArg 值的副本。xInit()方法的意图是设置自定义页面缓存实现所需的全局数据结构。如果xInit()方法为 NULL,则使用内置的默认页面缓存而不是应用程序定义的页面缓存。
xShutdown()方法由 sqlite3_shutdown()调用。如果需要,它可以用于在过程关闭之前清理任何未完成的资源。xShutdown()方法可能为 NULL。
SQLite 自动将调用序列化到 xInit 方法,所以 xInit 方法不需要是线程安全的。xShutdown 方法仅从 sqlite3_shutdown()调用,因此它不需要是线程安全的。所有其他方法在多线程应用程序中必须是线程安全的。
如果没有对 xShutdown()的干预调用,SQLite 将永远不会调用 xInit()。
SQLite 调用 xCreate()方法来构造一个新的缓存实例。SQLite 通常会为每个打开的数据库文件创建一个缓存实例,但不能保证。第一个参数 szPage 是必须由缓存分配的页面的大小(以字节为单位)。szPage 将永远是两个幂。第二个参数szExtra 是与每个页面缓存条目关联的额外存储的字节数。szExtra 参数的数字小于250。SQLite 将在每个页面上使用额外的 szExtra 字节来存储关于磁盘上基础数据库页面的元数据。传递给 szExtra 的值取决于 SQLite 版本,目标平台以及 SQLite的编译方式。如果正在创建的缓存将用于缓存存储在磁盘上的文件的数据库页,则 xCreate()的第三个参数是 bPurgeable,如果它用于内存数据库,则为 false。缓存实现不需要根据 bPurgeable 的值做任何特殊的事情; 它纯粹是咨询。在bPurgeable 为 false 的缓存上,SQLite 将永远不会调用 xUnpin(),除非故意删除一个页面。换句话说,在 bPurgeable 设置为 false 的缓存上调用 xUnpin()将始终将“discard”标志设置为 true。因此,使用 bPurgeable false创建的缓存将永远不会包含任何未锁定的页面。在 bPurgeable 设置为 false 的缓存上调用 xUnpin()将始终将“discard”标志设置为 true。因此,使用 bPurgeable false创建的缓存将永远不会包含任何未锁定的页面。在 bPurgeable 设置为 false 的缓存上调用 xUnpin()将始终将“discard”标志设置为 true。因此,使用 bPurgeable false 创建的缓存将永远不会包含任何未锁定的页面。
SQLite 可以随时调用 xCachesize()方法来设置作为第一个参数传递的缓存实例的建议最大缓存大小(存储的页面数)。这是使用 SQLite“PRAGMA cache_size”命令配置的值。与 bPurgeable 参数一样,实现不需要对此值做任何事情; 它只是咨询。
xPagecount()方法必须返回当前存储在缓存中的页数,这两个页都是固定的和未固定的。
xFetch()方法在缓存中查找页面,并返回指向与该页面关联的 sqlite3_pcache_page 对象的指针或 NULL 指针。返回的 sqlite3_pcache_page 对象的 pBuf 元素将是一个指向 szPage 字节缓冲区的指针,用于存储单个数据库页面的内容。sqlite3_pcache_page 的 pExtra 元素将成为 SQLite 为页面缓存中的每个条目请求的额外存储的 szExtra 字节的指针。
要获取的页面由密钥确定。最小键值为1。使用 xFetch 检索后,该页面被视为“固定”。
如果请求的页面已经在页面缓存中,那么页面缓存实现必须返回一个指向页面缓冲区的指针,其内容保持不变。如果请求的页面不在缓存中,那么缓存实现应该使用 createFlag 参数的值来帮助确定要采取的操作:
createFlag | 页面尚未进入缓存时的行为 |
---|---|
0 | 不要分配新的页面。返回 NULL。 |
1 | 如果能够轻松方便地分配新页面,请分配一个新页面。否则返回 NULL。 |
2 | 尽一切努力分配一个新的页面。只有在分配新页面时才返回 NULL 是不可能的。 |
SQLite 通常会使用0或1的 createFlag 调用 xFetch()。在先前的 createFlag 为1的调用失败之后,SQLite 将只使用2的 createFlag。在 xFetch()调用之间,SQLite 可以尝试通过将固定页面的内容泄漏到磁盘并同步操作系统磁盘高速缓存来解除一个或多个高速缓存页面的固定。
xUnpin()被 SQLite 用一个指向当前固定页面的指针作为第二个参数来调用。如果第三个参数 discard 非零,那么该页面必须从缓存中清除。如果丢弃参数为零,则可以根据页面缓存实施的意愿丢弃或保留该页面。页面缓存实现可以选择随时驱逐未固定的页面。
缓存不得执行任何引用计数。无论之前调用 xFetch()的次数,对 xUnpin()的单个调用都会取消页面。
xRekey()方法用于更改与作为第二个参数传递的页面关联的键值。如果高速缓存先前包含与 newKey 关联的条目,则必须丢弃该条目。任何与 newKey 关联的先前缓存条目都保证不被锁定。
当 SQLite 调用 xTruncate()方法时,缓存必须丢弃页码(键)大于或等于传递给 xTruncate()的 iLimit 参数值的所有现有缓存条目。如果这些页面中的任何一个被固定,则它们被隐式地取消固定,这意味着它们可以被安全地丢弃。
xDestroy()方法用于删除由 xCreate()分配的缓存。应该释放与指定缓存关联的所有资源。在调用 xDestroy()方法之后,SQLite 将 sqlite3_pcache *句柄视为无效,并且不会将其用于任何其他 sqlite3_pcache_methods2 函数。
SQLite 在希望页面缓存释放尽可能多的堆内存时调用 xShrink()方法。页面缓存实现没有义务释放任何内存,但良好行为的实现应尽其所能。
另请参见对象,常量和函数的列表。
SQLite is in the Public Domain.
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com