Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sqlite多线程并发时报空异常 #1938

Open
pardont opened this issue Dec 3, 2024 · 8 comments
Open

Sqlite多线程并发时报空异常 #1938

pardont opened this issue Dec 3, 2024 · 8 comments

Comments

@pardont
Copy link

pardont commented Dec 3, 2024

在android上多线程同时读写sqlite数据库时报错,极小概率。在android上运行10几个小时可能会出现下面的错误,在linux和windows上没有这个问题。

在efcore项目中有人遇到类似的问题:
dotnet/efcore#20651

会不会是连接池中的连接池不够用,导致多个线程使用了同一个连接导致的?

构造freesql单实例的代码如下:

_freesql = new FreeSql.FreeSqlBuilder()
                 .UseConnectionString(FreeSql.DataType.Sqlite", Data Source=data.db;")
                 .Build();

在android上运行10几个小时可能会出现下面的错误,在linux和windows上没有这个问题。

12-03 15:40:33.351  1507  2785 V mono-stdout: [Error]: Object reference not set to an instance of an object
12-03 15:40:33.351  1507  2785 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteConnection.RemoveCommand (Microsoft.Data.Sqlite.SqliteCommand command) [0x0001c] in <84cd3138e0a74f0a9108b847408e6ac1>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteCommand.Dispose (System.Boolean disposing) [0x00014] in <84cd3138e0a74f0a9108b847408e6ac1>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at System.ComponentModel.Component.Dispose () [0x00000] in <71e78ea04782456a9a4e3e211cdabfc0>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at (wrapper remoting-invoke-with-check) System.ComponentModel.Component.Dispose()
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.AdoProvider.ExecuteReaderMultiple (System.Int32 multipleResult, System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, System.Action`2[T1,T2] fetchHandler, System.Action`2[T1,T2] schemaHandler, System.Data.CommandType cmdType, System.String cmdText, System.Int32 cmdTimeout, System.Data.Common.DbParameter[] cmdParms) [0x0060f] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.AdoProvider.ExecuteReader (System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, System.Action`1[T] fetchHandler, System.Data.CommandType cmdType, System.String cmdText, System.Int32 cmdTimeout, System.Data.Common.DbParameter[] cmdParms) [0x0000d] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToListAfPrivate (System.String sql, FreeSql.Internal.CommonProvider.Select0Provider`2+GetAllFieldExpressionTreeInfo[TSelect,T1] af, FreeSql.Internal.Model.ReadAnonymousTypeOtherInfo[] otherData) [0x000eb] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToListPrivate (FreeSql.Internal.CommonProvider.Select0Provider`2+GetAllFieldExpressionTreeInfo[TSelect,T1] af, FreeSql.Internal.Model.ReadAnonymousTypeOtherInfo[] otherData) [0x0014e] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToList (System.Boolean includeNestedMembers) [0x000ce] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select1Provider`1[T1].ToList (System.Boolean includeNestedMembers) [0x00000] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToList () [0x00000] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at Wisdor.POS.Data.Services.Sqlite.SaleSummaryService.GetUnuploadBills (System.Int32 limit) [0x000f2] in <db439cfd6ace4be494971b781933cd50>:0 
12-03 15:40:33.357   292  2788 V [email protected]: @dequeueV4l2FrameLocked(3866) select time begin 
12-03 15:40:33.362  1507  1507 V mono-stdout: [Error]: Object reference not set to an instance of an object
12-03 15:40:33.362  1507  1507 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteConnection.RemoveCommand (Microsoft.Data.Sqlite.SqliteCommand command) [0x0001c] in <84cd3138e0a74f0a9108b847408e6ac1>:0 
12-03 15:40:33.362  1507  1507 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteCommand.Dispose (System.Boolean disposing) [0x00014] in <84cd3138e0a74f0a9108b847408e6ac1>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at System.ComponentModel.Component.Dispose () [0x00000] in <71e78ea04782456a9a4e3e211cdabfc0>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at (wrapper remoting-invoke-with-check) System.ComponentModel.Component.Dispose()
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.AdoProvider.ExecuteReaderMultiple (System.Int32 multipleResult, System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, System.Action`2[T1,T2] fetchHandler, System.Action`2[T1,T2] schemaHandler, System.Data.CommandType cmdType, System.String cmdText, System.Int32 cmdTimeout, System.Data.Common.DbParameter[] cmdParms) [0x0060f] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.AdoProvider.ExecuteReader (System.Data.Common.DbConnection connection, System.Data.Common.DbTransaction transaction, System.Action`1[T] fetchHandler, System.Data.CommandType cmdType, System.String cmdText, System.Int32 cmdTimeout, System.Data.Common.DbParameter[] cmdParms) [0x0000d] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToListAfPrivate (System.String sql, FreeSql.Internal.CommonProvider.Select0Provider`2+GetAllFieldExpressionTreeInfo[TSelect,T1] af, FreeSql.Internal.Model.ReadAnonymousTypeOtherInfo[] otherData) [0x000eb] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToListPrivate (FreeSql.Internal.CommonProvider.Select0Provider`2+GetAllFieldExpressionTreeInfo[TSelect,T1] af, FreeSql.Internal.Model.ReadAnonymousTypeOtherInfo[] otherData) [0x0014e] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToList (System.Boolean includeNestedMembers) [0x000ce] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select1Provider`1[T1].ToList (System.Boolean includeNestedMembers) [0x00000] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToList () [0x00000] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].ToOne () [0x00009] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at FreeSql.Internal.CommonProvider.Select0Provider`2[TSelect,T1].First () [0x00000] in <9fbe70c7241946a0b65260e7c7fba30d>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at Wisdor.POS.Data.Services.Sqlite.PluService.QueryRow (System.String barcode) [0x0008f] in <db439cfd6ace4be494971b781933cd50>:0 
12-03 15:40:33.363  1507  1507 V mono-stdout:   at Wisdor.POS.BLL.Default.BarcodeLogic.ProcessBarcode (System.String barcode, System.Object extensionData) [0x001fd] in <db439cfd6ace4be494971b781933cd50>:0 

数据库版本

Sqlite3

安装的Nuget包

FreeSql: 3.2.682
FreeSql.Provider.Sqlite: 3.2.682
Microsoft.Data.Sqlite: 6.0.10

.net framework/. net core? 及具体版本

Xamarin.Forms: 5.0.0.1874

@2881099
Copy link
Collaborator

2881099 commented Dec 3, 2024

sqlite不支持多线程写

@pardont
Copy link
Author

pardont commented Dec 3, 2024

有什么推荐的做法吗?我在linux和windows上也是相同的程序写法,没有问题呀

@pardont
Copy link
Author

pardont commented Dec 4, 2024

sqlite不支持多线程写

有没有什么思路或者建议?从Microsoft.Data.Sqlite库那边的描述是说要避免多线程使用同一个连接,是不是可以从FreeSql的连接池着手?

@2881099
Copy link
Collaborator

2881099 commented Dec 4, 2024

freesql 层面每次都是独立的 DbConnection

@pardont
Copy link
Author

pardont commented Dec 5, 2024

sqlite不支持多线程写

我测试了一下,在数据库中插入了1000多条数据,然后开了10个线程读取数据,不做写操作,就会出现空异常

2-03 15:40:33.351  1507  2785 V mono-stdout: [Error]: Object reference not set to an instance of an object
12-03 15:40:33.351  1507  2785 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteConnection.RemoveCommand (Microsoft.Data.Sqlite.SqliteCommand command) [0x0001c] in <84cd3138e0a74f0a9108b847408e6ac1>:0 
12-03 15:40:33.351  1507  2785 V mono-stdout:   at Microsoft.Data.Sqlite.SqliteCommand.Dispose (System.Boolean disposing) [0x00014] in <84cd3138e0a74f0a9108b847408e6ac1>:0 

如果在多线程操作中再加上写操作,会出现数据库被锁定的异常。

所以多线程只是读取数据,会出现空异常,是不是说明同一个数据库连接在同一个时间点上被多个线程使用了?

@2881099
Copy link
Collaborator

2881099 commented Dec 5, 2024

用 FreeSql.provider.Sqlite.dll 测试一下

@2881099
Copy link
Collaborator

2881099 commented Dec 5, 2024

同时用一个 DbConnection 读是不可能的,如果有早就有人反馈了。

@pardont
Copy link
Author

pardont commented Dec 11, 2024

FreeSql.provider.Sqlite.dll 没办法在android上跑吧。

我把库都升级到最新,概率大幅下降了,原本10线程在android上大概700-800次就会出现,升级后大概大几千次出现一次。

我暂时的想法是把所有的调用代码都加上try catch处理掉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants