求助:如何解决c#多线程写入sqlite的 SQLite error (5): database is locked 错误?

tylrr 2014-06-02 02:12:35
如题,c#+sqlite数据库。程序使用了多线程调用getlinks 函数,写入数据到sqlite里面,但是程序总是报错:


SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked
SQLite error (5): database is locked




#region //提取搜索结果中的宝贝链接
private void getlinks(object workmode)
{
...................省略部分代码

//写入数据库
try
{
SQLiteConnection mycon = new SQLiteConnection();
SQLiteConnectionStringBuilder connsb = new SQLiteConnectionStringBuilder();
connsb.DataSource = dbName;
mycon.ConnectionString = connsb.ToString();
mycon.Open();
for (int i = 0; i < itemlinks.Count; i++)
{
SQLiteCommand mycmd = new SQLiteCommand();
switch (workmode.ToString())
{
case "a":
mycmd = new SQLiteCommand(string.Format("insert INTO itemdetails(itemid,checkedtime,itemurl) select '{0}','{1}','{2}' where not exists(select itemid,checkedtime from itemdetails where itemid='{0}'); ", getItemid(itemlinks[i]), checkedtime, itemlinks[i]), mycon);
mycmd.ExecuteNonQuery();
mycmd = new SQLiteCommand(string.Format("update itemdetails set zhrank={0} where itemid={1};", i + 1,getItemid(itemlinks[i])), mycon);
mycmd.ExecuteNonQuery();
break;

case "b":
mycmd = new SQLiteCommand(string.Format("insert INTO itemdetails(itemid,checkedtime,itemurl) select '{0}','{1}','{2}' where not exists(select itemid,checkedtime from itemdetails where itemid='{0}'); ", getItemid(itemlinks[i]), checkedtime, itemlinks[i]), mycon);
mycmd.ExecuteNonQuery();
mycmd = new SQLiteCommand(string.Format("update itemdetails set rqrank={0} where itemid={1};", i + 1, getItemid(itemlinks[i])), mycon);
mycmd.ExecuteNonQuery();
break;

case "c":
mycmd = new SQLiteCommand(string.Format("insert INTO itemdetails(itemid,checkedtime,itemurl) select '{0}','{1}','{2}' where not exists(select itemid,checkedtime from itemdetails where itemid='{0}'); ", getItemid(itemlinks[i]), checkedtime, itemlinks[i]), mycon);
mycmd.ExecuteNonQuery();
mycmd = new SQLiteCommand(string.Format("update itemdetails set xlrank={0} where itemid={1};", i + 1, getItemid(itemlinks[i])), mycon);
mycmd.ExecuteNonQuery();
break;

case "d":
mycmd = new SQLiteCommand(string.Format("insert INTO itemdetails(itemid,checkedtime,itemurl) select '{0}','{1}','{2}' where not exists(select itemid,checkedtime from itemdetails where itemid='{0}'); ", getItemid(itemlinks[i]), checkedtime, itemlinks[i]), mycon);
mycmd.ExecuteNonQuery();
mycmd = new SQLiteCommand(string.Format("update itemdetails set tmrank={0} where itemid={1};", i + 1, getItemid(itemlinks[i])), mycon);
mycmd.ExecuteNonQuery();
break;
}
}

mycon.Close(); //关闭数据库连接
}

catch (Exception e)
{
MessageBox.Show(e.ToString());
}


请问应该如何解决呢? 求详细代码 谢谢!
...全文
605 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
tylrr 2014-06-03
  • 打赏
  • 举报
回复
引用 3 楼 tanta 的回复:
你这资源占用得多高啊,在循环中连续生成Command对象。而且重复生成,有的根本没有用。还多线程调用,设计思路混乱。 设计的问题用设计技巧很难彻底解决,这儿解决了,其他地方也会出问题,就像战略问题无法用战术方法解决一样。 还是先进行系统分析,重新设计下你的软件吧。 建议系统的学习下数据库编程,而不是看几个例子就写代码。 针对你的代码,提几个建议: 1、command对象在循环外生成一个就够了,在需要的地方改变commandText 就可以了; 2、少用拼接字符串方式生成SQL语句,多用Parameters.Add(); 3、数据库尽量不要并发操作,确需并发,考虑数据库锁问题。关于SQLite锁,参考: http://my.oschina.net/u/587236/blog/129022 4、没看到你的数据库设计,总感觉味道不是很好。 5、既然参数object workmode是字符型,为什么不直接设为string?其他地方要用到其他数据类型?这个设计。。。 啰嗦好多,没有恶意,都是从新手来的,说得不对的地方,多包涵。
你好,非常感谢你的指正。 1、针对第一条 command对象的问题,我已经按你所说的改成改变commandText 了。2、多用Parameters.Add是为了防止被注入么?有没有性能上的提升? 3、这篇资料我完全看不懂啊,可否给些c#的实例代码?非常感谢。5、其他地方要用到object数据类型
tylrr 2014-06-03
  • 打赏
  • 举报
回复
引用 1 楼 rtdb 的回复:
sqlite threading mode set to Serialized
请问如何设置呢? 是否需要重新编译sqlite 还是直接在程序语句中写代码实现 ? 可否详细说一下 谢谢
gnimgnot 2014-06-03
  • 打赏
  • 举报
回复
sqlite锁了。 记住:sqlite是写独占,读并发。 如果有写操作,一定要做好线程同步(甚至进程同步)。否则其默认的生为在报锁的时候立即返回,而不是重试,这个时候你就得想办法保证数据的一致性了。 在有写操作的时候,注意加锁或临界区,你可以选择在失败的时候重试,当然具体的手段就看你自己的实现了。
tcmakebest 2014-06-03
  • 打赏
  • 举报
回复
sqlite就不要多线程了。
tanta 2014-06-03
  • 打赏
  • 举报
回复
3、
引用 5 楼 tylrr 的回复:
[quote=引用 3 楼 tanta 的回复:] 你这资源占用得多高啊,在循环中连续生成Command对象。而且重复生成,有的根本没有用。还多线程调用,设计思路混乱。 设计的问题用设计技巧很难彻底解决,这儿解决了,其他地方也会出问题,就像战略问题无法用战术方法解决一样。 还是先进行系统分析,重新设计下你的软件吧。 建议系统的学习下数据库编程,而不是看几个例子就写代码。 针对你的代码,提几个建议: 1、command对象在循环外生成一个就够了,在需要的地方改变commandText 就可以了; 2、少用拼接字符串方式生成SQL语句,多用Parameters.Add(); 3、数据库尽量不要并发操作,确需并发,考虑数据库锁问题。关于SQLite锁,参考: http://my.oschina.net/u/587236/blog/129022 4、没看到你的数据库设计,总感觉味道不是很好。 5、既然参数object workmode是字符型,为什么不直接设为string?其他地方要用到其他数据类型?这个设计。。。 啰嗦好多,没有恶意,都是从新手来的,说得不对的地方,多包涵。
你好,非常感谢你的指正。 1、针对第一条 command对象的问题,我已经按你所说的改成改变commandText 了。2、多用Parameters.Add是为了防止被注入么?有没有性能上的提升? 3、这篇资料我完全看不懂啊,可否给些c#的实例代码?非常感谢。5、其他地方要用到object数据类型[/quote] ========================================================== 2、除了防注入外,性能有一定提升,还有,图像、二进制等拼接SQL无法完成,用Parameters就很方便。 3、没研究过SQLite的锁,抱歉。 5、建议你将这一个函数拆分成两个函数。
tanta 2014-06-02
  • 打赏
  • 举报
回复
你这资源占用得多高啊,在循环中连续生成Command对象。而且重复生成,有的根本没有用。还多线程调用,设计思路混乱。 设计的问题用设计技巧很难彻底解决,这儿解决了,其他地方也会出问题,就像战略问题无法用战术方法解决一样。 还是先进行系统分析,重新设计下你的软件吧。 建议系统的学习下数据库编程,而不是看几个例子就写代码。 针对你的代码,提几个建议: 1、command对象在循环外生成一个就够了,在需要的地方改变commandText 就可以了; 2、少用拼接字符串方式生成SQL语句,多用Parameters.Add(); 3、数据库尽量不要并发操作,确需并发,考虑数据库锁问题。关于SQLite锁,参考: http://my.oschina.net/u/587236/blog/129022 4、没看到你的数据库设计,总感觉味道不是很好。 5、既然参数object workmode是字符型,为什么不直接设为string?其他地方要用到其他数据类型?这个设计。。。 啰嗦好多,没有恶意,都是从新手来的,说得不对的地方,多包涵。
tylrr123 2014-06-02
  • 打赏
  • 举报
回复
请问如何设置呢? 是否需要重新编译sqlite 还是直接在程序语句中写代码实现 ? 可否详细说一下 谢谢
rtdb 2014-06-02
  • 打赏
  • 举报
回复
sqlite threading mode set to Serialized

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧