#2263·libsql

在一个进程中,STATUS_ACCESS_VIOLATION (0xC0000005) 错误出现在并发 Builder::new_local(...)。build() 函数中(Windows,0.9.30)

作者: opticsWolf创建于 2026年7月30日更新于 2026年7月30日

async fn one(path: PathBuf) { let db = libsql::Builder::new_local(&path).build().await.expect("build"); let conn = db.connect().expect("connect"); conn.execute("CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY, v TEXT)", ()) .await .expect("create"); conn.execute("INSERT INTO t (v) VALUES ('x')", ()).await.expect("insert"); drop(conn); drop(db); } #[tokio::main] async fn main() { let args: Vec = env::args().collect(); let mode = args.get(1).map(String::as_str).unwrap_or("churn"); let n: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(500); let dir = tempfile::tempdir().expect("tempdir"); match mode { // One at a time. "churn" => { for i in 0..n { one(dir.path().join(format!("db{i}.sqlite"))).await; } } // All at once. "concurrent" => { let mut handles = Vec::with_capacity(n); for i in 0..n { handles.push(tokio::spawn(one(dir.path().join(format!("db{i}.sqlite"))))); } for h in handles { h.await.expect("task"); } } // All at once, and nothing is dropped until every task has finished. "hold" => { let mut handles = Vec::with_capacity(n); for i in 0..n { let p = dir.path().join(format!("db{i}.sqlite")); handles.push(tokio::spawn(async move { let db = libsql::Builder::new_local(&p).build().await.expect("build"); let conn = db.connect().expect("connect"); conn.execute("CREATE TABLE IF NOT EXISTS t (id INTEGER PRIMARY KEY)", ()) .await .expect("create"); (conn, db) }); } let mut kept = Vec::with_capacity(n); for h in handles { let (conn, db) = h.await.expect("task"); kept.push((conn, db)); } for (conn, db) in kept { conn.execute("DELETE FROM t", ()).await.expect("delete"); db.close().await.expect("close"); } } } }

内容来源: tursodatabase/libsql