【发布时间】:2019-04-25 10:08:12
【问题描述】:
我对同一张表的多线程插入有疑问。从错误消息看来,PK被复制了:
错误:
外键约束失败
表格:
-- Logs
CREATE TABLE "Logs" (
"Id" INTEGER PRIMARY KEY,
"Time" DATETIME NOT NULL,
"Message" TEXT NOT NULL,
"OtherObjId" INTEGER NOT NULL,
FOREIGN KEY(OtherObjId) REFERENCES OtherObjs(Id) ON DELETE CASCADE
);
CREATE INDEX IDX_Logs ON Logs (OtherObj);
代码(可能从多个线程调用异步):
public async Task AddLogAsync(Log log) {
using (var cmd = _conn.CreateCommand()) {
cmd.CommandText = $"INSERT INTO Logs (Time, Message, OtherObjId) VALUES ('{DateTime.UtcNow}', @message, @OtherObjId);";
cmd.Parameters.AddWithValue("@message", log.Message);
cmd.Parameters.AddWithValue("@otherObjId", log.OtherObj.Id);
await cmd.ExecuteNonQueryAsync();
}
}
我的理解是 Sqlite 数据库不应该有这个问题,因为它在 serialised 模式下运行,带有标志 THREADSAFE=1。它应该对多个插入进行排队,并为每个插入提供不同的 PK。
我也在使用以下PRAGMAs:
PRAGMA synchronous=NORMAL;
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
我正在使用带有 .NET 程序集的 SQLite v3.27.2。
更新
它似乎与FOREIGN KEY 有关(谢谢蒂姆·比格莱森。我怎么能想到其他呢?)。我已经做了一些检查,并且之前已经添加了外键的记录。一些调试输出:
Log about to be added for otherObj id 1
otherObj added with id 2
Log about to be added for otherObj id 2
otherObj added with id 3
Log about to be added for otherObj id 3
otherObj added with id 4
Log about to be added for otherObj id 4
otherObj added with id 5
Log about to be added for otherObj id 5
otherObj added with id 6
Log about to be added for otherObj id 6
otherObj added with id 7
Log about to be added for otherObj id 7
otherObj added with id 8
Log about to be added for otherObj id 8
otherObj added with id 9
Log about to be added for otherObj id 9
otherObj added with id 10
Log about to be added for otherObj id 10
otherObj added with id 11
Log about to be added for otherObj id 11
otherObj added with id 12
Log about to be added for otherObj id 12
otherObj added with id 13
Log about to be added for otherObj id 13
otherObj added with id 14
Log about to be added for otherObj id 14
otherObj added with id 15
Log about to be added for otherObj id 15
otherObj added with id 16
Log about to be added for otherObj id 16
Log about to be added for otherObj id 1
Log about to be added for otherObj id 2
Log about to be added for otherObj id 3
otherObj added with id 17
Log about to be added for otherObj id 17
Log about to be added for otherObj id 4
otherObj added with id 18
Log about to be added for otherObj id 18
Log about to be added for otherObj id 5
otherObj added with id 19
Log about to be added for otherObj id 19
Log about to be added for otherObj id 6
otherObj added with id 20
Log about to be added for otherObj id 20
Log about to be added for otherObj id 7
Log about to be added for otherObj id 8
otherObj added with id 461
Log about to be added for otherObj id 461
SQLite error (787): abort at 21 in [INSERT INTO Logs (Time, Message, otherObjId) VALUES ('25/04/2019 11:35:27', @message, @otherObjId);]: FOREIGN KEY constraint failed
Exception thrown: 'System.Data.SQLite.SQLiteException' in System.Private.CoreLib.dll
Log about to be added for otherObj id 9
Exception thrown: 'System.Data.SQLite.SQLiteException' in System.Private.CoreLib.dll
An exception of type 'System.Data.SQLite.SQLiteException' occurred in System.Private.CoreLib.dll but was not handled in user code
constraint failed
FOREIGN KEY constraint failed
可以看出otherObj id 9是很久以前添加的,但失败仍然发生。
【问题讨论】:
标签: c# multithreading sqlite foreign-keys constraints