⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
Concurrency

处理并发

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

  1. 一个进程可以同时读取和写入数据库。
  2. 多个进程可以从数据库中读取,但没有进程可以写入 (access_mode = 'READ_ONLY').

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

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

单进程内的并发

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

从多个进程写入DuckDB

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

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

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

乐观并发控制

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

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

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