EF高并发处理 这种情况如何处理,请教各位

atmo 2017-10-11 02:28:38
流程是这样的
每个用户提交后插入新数据 20条
每插入一条后 更新总数 update一下总表
两个用户的提交结果就是 记录数40条,总表的数据为2

我用EF的save()方法,发现数据不全,比如有的记录只有15条,每个用户应该是20条,到了15就没有记录了,总表的数据也和投票数对不上,两个问题
1、插入15条的时候,说明已经执行到了save方法,但可能在16条的时候报错,每秒插入的数据在200多,每秒update的数量应该在10个以上,这个报错是不是因为数据库并发造成的?

2、如果上述问题是并发造成的,那么是insert造成的并发还是update造成的并发冲突?
3、如果以上数据量不足以造成这种情况,那其他原因都有什么?(Save()执行了一半)
...全文
973 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
atmo 2017-10-13
  • 打赏
  • 举报
回复
引用 16 楼 foren_whb 的回复:
你这那里看出来是高并发了??? 只是个普通的并发问题,不要把所有的并发问题都归结为高并发,那完全不是一回事 并发问题,通常是代码逻辑考虑不周,导致并发冲突产生的 而高并发问题,通常是硬件环境和框架设计对并发处理的能力不足导致的, 根本不是一回事!!!! 你这是典型的代码逻辑导致的错误,在实现插入业务的时候,没有考虑好并发冲突,
说的好!
atmo 2017-10-12
  • 打赏
  • 举报
回复
问题解决了 这完全是数据库设计问题 两条语句搞定了 insert 记录表 用户ID 投票项目ID 1 1,2,3,4,5,6,7...20 update 用户投票总表 update 表 set count=count+1 where 投票id in(1,2,3,4,5,6) 每一次操作少了38次数据查询.... 感谢各位
丰云 2017-10-12
  • 打赏
  • 举报
回复
你这那里看出来是高并发了??? 只是个普通的并发问题,不要把所有的并发问题都归结为高并发,那完全不是一回事 并发问题,通常是代码逻辑考虑不周,导致并发冲突产生的 而高并发问题,通常是硬件环境和框架设计对并发处理的能力不足导致的, 根本不是一回事!!!! 你这是典型的代码逻辑导致的错误,在实现插入业务的时候,没有考虑好并发冲突,
圣殿骑士18 2017-10-12
  • 打赏
  • 举报
回复
问题很明显就是,更新的时候锁死了。这个只能从设计上优化。更新频率没有必要这么高。可以在表一上加个标记字段,没有更新的行标记为1,每五秒或者十秒统一批量更新一次(一个sql)。
圣殿骑士18 2017-10-12
  • 打赏
  • 举报
回复
明明就一个总表,怎么说成20个总表?
qq_25147077 2017-10-11
  • 打赏
  • 举报
回复
你既然能确认报错,那为何不把具体错误捕捉下来,然后根据错误再来分析到底是什么引起的
atmo 2017-10-11
  • 打赏
  • 举报
回复
上面说的模糊了 就是这样 ------投票记录表----- 用户ID 小孩ID 1 1 1 2 1 3 ------小孩票数表----- 小孩ID 票数 1 12 2 23 3 31 一个用户一次给20个小孩每一个人投一票,共一次投20票,并更新 小孩的票数 就这么简单
atmo 2017-10-11
  • 打赏
  • 举报
回复
引用 4 楼 apple8160 的回复:
为什么不把20条记录 一次执行save? save执行后获取影响行数 然后把行数update?
实际上是这样的20条记录insert之后,还要让这20条记录对应的20个总表每一个都加1,看来表设计有问题啊[/quote] 有点没看明白 你的意思是 20张表对应20张总表 还是1张表20条记录 对应20张总表??[/quote] 实际上是给孩子投票 用户一次投20个票,投给20个孩子,每个孩子只能投一票,我给每个孩子设计了一个总表,所以结果就是用户一次投20票,每个人一票,还要去孩子的表里面去加1 ------投票记录表----- 用户ID 小孩ID 1 1 1 2 1 3 ------小孩票数表----- 小孩ID 票数 1 12 2 23 3 31 这个意思 如何优化一下
guanyelong 2017-10-11
  • 打赏
  • 举报
回复
建议用批量插入更新的方法举个小例子 SqlBulkCopy 用法

        public static bool UpdateBuikForCardInOut(DataTable dt, DataTable dtpool, string cardids)
        {
            SqlConnection sqlCon = new SqlConnection(conStr);
            sqlCon.Open();
            SqlTransaction sqlTran = sqlCon.BeginTransaction(); // 开始事务
            try
            {
                SqlBulkCopy sqlBC = new SqlBulkCopy(sqlCon, SqlBulkCopyOptions.Default, sqlTran);
                sqlBC.DestinationTableName = dt.TableName;
                sqlBC.BatchSize = 500;
                foreach (DataColumn dc in dt.Columns)
                {
                    sqlBC.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
                }
                sqlBC.WriteToServer(dt);
                bool succ = UpdateBuikForCardPool(dtpool, sqlCon, sqlTran, cardids);
                if (succ)
                {
                    sqlTran.Commit();
                    return true;
                }
                else
                {
                    sqlTran.Rollback();
                    return false;
                }
            }
            catch (Exception)
            {
                sqlTran.Rollback();
                return false;
            }
        }

public static bool UpdateBuikForCardPool(DataTable dtpool, SqlConnection sqlCon, SqlTransaction sqlTran, string cardids)
        {
            try
            {
                SqlBulkCopy sqlBC = new SqlBulkCopy(sqlCon, SqlBulkCopyOptions.Default, sqlTran);
                var arry = cardids.Split(',');
                foreach (var item in arry)
                {
                    string sql = "delete from tb_Card_Pool where CardId in ('" + item + "')";
                    using (SqlCommand cmd = new SqlCommand(sql, sqlCon, sqlTran))
                    {
                        int num = cmd.ExecuteNonQuery();
                    }
                }

                sqlBC.DestinationTableName = dtpool.TableName;
                sqlBC.BatchSize = 500;
                foreach (DataColumn dc in dtpool.Columns)
                {
                    sqlBC.ColumnMappings.Add(dc.ColumnName, dc.ColumnName);
                }
                sqlBC.WriteToServer(dtpool);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
apple8160 2017-10-11
  • 打赏
  • 举报
回复
引用 5 楼 atmo 的回复:
[quote=引用 4 楼 apple8160 的回复:] 为什么不把20条记录 一次执行save? save执行后获取影响行数 然后把行数update?
实际上是这样的20条记录insert之后,还要让这20条记录对应的20个总表每一个都加1,看来表设计有问题啊[/quote] 有点没看明白 你的意思是 20张表对应20张总表 还是1张表20条记录 对应20张总表??
atmo 2017-10-11
  • 打赏
  • 举报
回复
引用 4 楼 apple8160 的回复:
为什么不把20条记录 一次执行save? save执行后获取影响行数 然后把行数update?
实际上是这样的20条记录insert之后,还要让这20条记录对应的20个总表每一个都加1,看来表设计有问题啊
apple8160 2017-10-11
  • 打赏
  • 举报
回复
个人看法 2张表 1张记录小孩信息表 1张投票表 也就是 --> 用户id,小孩id ,投票时间 其他多余
apple8160 2017-10-11
  • 打赏
  • 举报
回复
为什么不把20条记录 一次执行save? save执行后获取影响行数 然后把行数update?
xdashewan 2017-10-11
  • 打赏
  • 举报
回复
引用 2 楼 atmo 的回复:
事务(进程 ID 60)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务 save的时候提示这个错误
你事务对两张表是如何操作的,看你的描述应该有两个事务,一个事务保证20条数据插入完整,而另一事务用来update+1
exception92 2017-10-11
  • 打赏
  • 举报
回复
在方法中加DbTransaction 事物测试。
atmo 2017-10-11
  • 打赏
  • 举报
回复
事务(进程 ID 60)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务 save的时候提示这个错误
xdashewan 2017-10-11
  • 打赏
  • 举报
回复
你既然能确认报错,那为何不把具体错误捕捉下来,然后根据错误再来分析到底是什么引起的

62,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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