我对同一个表进行多线程插入时遇到问题。从错误消息看来,PK已被复制:
错误:
FOREIGN KEY约束失败
表格:
-- 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。
我还使用以下PRAGMA
:
PRAGMA synchronous=NORMAL;
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
我正在使用.NET程序集使用SQLite v3.27.2。
似乎它与FOREIGN KEY
有关(谢谢蒂姆·比格里森(Tim Biegeleisen)。我怎么可能不这么认为?)。我已经做了一些检查,外键的记录也早已添加。一些调试输出:
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,但故障仍然发生。
答案 0 :(得分:1)
从错误消息中可以看到,故障实际上与Logs
表中的 foreign 键有关:
FOREIGN KEY约束失败
最有可能发生故障,因为您的一个或多个插入使用的是OtherObjId
值,该值在Id
表中没有对应的OtherObjs
映射。要解决此问题,您应该调查OtherObjId
值的来源,并确保它们在OtherObjs
中具有父记录。也许存在多线程问题,或者可能还有其他原因。