⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
并发

处理并发

DuckDB 有两个可配置的并发选项

  1. 一个进程可以同时对数据库进行读写操作。
  2. 多个进程可以从数据库读取,但不能写入(access_mode = 'READ_ONLY')。

使用选项1时,DuckDB 结合 MVCC(多版本并发控制)和乐观并发控制(参见单个进程内的并发)支持多个写入线程,但所有操作都在该单个写入进程内进行。这种并发模型的原因是为了允许将数据缓存到 RAM 中,以便进行更快的分析查询,而不是在每次查询期间频繁地读写磁盘。它还允许缓存函数指针、数据库目录和其他项目,从而使同一连接上的后续查询更快。

DuckDB 针对批量操作进行了优化,因此执行许多小型事务并非其主要设计目标。

单个进程内的并发

DuckDB 按照以下规则支持单个进程内的并发。只要没有写入冲突,多个并发写入都将成功。追加操作永远不会冲突,即使在同一张表上也是如此。多个线程还可以同时更新不同的表或同一表的独立子集。当两个线程同时尝试编辑(更新或删除)同一行时,乐观并发控制就会发挥作用。在这种情况下,第二个尝试编辑的线程将因冲突错误而失败。

从多个进程写入 DuckDB

不支持从多个进程自动写入 DuckDB,这不是主要设计目标(参见处理并发)。

如果多个进程必须写入同一文件,则有几种设计模式是可行的,但需要在应用程序逻辑中实现。例如,每个进程可以获取一个跨进程互斥锁,然后以读/写模式打开数据库并在查询完成后关闭。除了使用互斥锁,每个进程还可以选择在另一个进程已连接到数据库时重试连接(确保在查询完成后关闭连接)。另一种替代方案是在 MySQL、PostgreSQL 或 SQLite 数据库上执行多进程事务,并使用 DuckDB 的 MySQLPostgreSQLSQLite 扩展定期对这些数据执行分析查询。

其他选项包括将数据写入 Parquet 文件并利用 DuckDB 读取多个 Parquet 文件的能力,或对 CSV 文件采取类似的方法,或者创建一个 Web 服务器来接收请求并管理对 DuckDB 的读写操作。

乐观并发控制

DuckDB 使用乐观并发控制,这种方法通常被认为是读取密集型分析数据库系统的最佳选择,因为它能加快读取查询的处理速度。因此,任何同时修改相同行的事务都将导致事务冲突错误。

Transaction conflict: cannot update a table that has been altered!

提示 当遇到事务冲突时,常见的解决方法是重新运行该事务。