由于行数很多(超过一百万)的数据库表中实体的一个接一个的更新,因此我们的应用程序出现性能问题。我们一直在遇到死锁受害者错误,因此很显然,表锁定行的时间比应有的长。
当前,我们实现了存储过程调用的可配置限制/时间阈值的手动批处理,以更新数据库中的实体。
简化的类如下所示:
public class EntityBatchUpdater
{
private readonly IRepository _repository;
private List<Entity> _batch = new List<Entity>();
private readonly Timer _batchPostingTimer;
private readonly int _batchSize;
private static readonly object _batchPostingLock = new object();
public EntityBatchUpdater(IRepository repository)
{
_repository = repository;
_batchSize = 1000; // configurable
string batchPostingPeriod = "00:01:00.00"; // configurable
_batchPostingTimer = new Timer
{
Interval = TimeSpan.Parse(batchPostingPeriod).TotalMilliseconds,
Enabled = true,
AutoReset = true,
};
_batchPostingTimer.Elapsed += OnTimedEvent;
}
public void Update(Entity entity)
{
try
{
lock (_batchPostingLock)
{
_batch.Add(entity);
if (_batch.Count == _batchSize)
{
EntityBatchUpdate();
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Failed to insert batch {JsonConvert.SerializeObject(batch)}");
}
}
private void EntityBatchUpdate()
{
if (_batch.Count == 0)
{
return;
}
try
{
var entityBatchXML = SerializePayload();
_repository.BatchUpdate(entityBatchXML);
_batch.Clear();
}
catch (Exception ex)
{
_logger.LogError(ex, $"Failed to insert batch; batchSize:{_batch.Count}");
}
}
private string SerializePayload()
{
using (var sw = new System.IO.StringWriter())
{
XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
ns.Add("", "");
var serializer = new XmlSerializer(typeof(List<Entity>),
new XmlRootAttribute("ENTITY_BATCH"));
serializer.Serialize(sw, _batch, ns);
return sw.ToString();
}
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
EntityBatchUpdate();
}
}
当前,我们利用SQL Server的快速XML处理功能,并在调用实际过程时将有效负载序列化为XML,以避免通过大量调用访问数据库。我还考虑过创建一个表值参数来序列化我们需要发送给proc的数据,但是我认为这不会大大提高性能。
我的问题是:您是如何处理数据库上的此类大负载的?1.)您是否使用nuget包/其他工具来为您处理批处理?2)您是否使用其他实践解决了这个问题?
编辑:提供更多的见解:我们当前正在应用程序中手动处理队列(因此有大量更新),并且我们希望尽可能快且可靠地进行处理。将来,我们将使用更好的排队机制(RabbtiMQ或Kafka),但是与此同时,我们希望拥有一种使用和处理数据库表中队列的标准方法。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。