У меня проблема с многопоточными вставками в одну таблицу.Из сообщения об ошибке видно, что 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
s:
PRAGMA synchronous=NORMAL;
PRAGMA journal_mode=WAL;
PRAGMA foreign_keys=ON;
Я использую SQLite v3.27.2 с использованиемСборки .NET.
Обновление
Кажется, это связано с 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
Как можно видеть, id 9 otherObj был добавлен задолго до этого, но сбой все же произошел.