与Azure SQL数据库的可靠连接

时间:2016-01-16 15:43:33

标签: c# sql-server azure azure-sql-database

我开发了一个在Azure SQL数据库中存储数据的C#应用​​程序。

您可能知道,Azure SQL数据库位于Internet上的某个位置。不是通过LAN网络(但这个问题也与LAN等可靠网络有关)。

我注意到我不时会收到“连接已关闭”(或其他网络错误)等错误。用Clumsy模拟这个很容易。出现这些错误的原因是网络状况不佳。

所以,我解决这个问题的第一个想法是“再试一次”。当我收到此错误时,我只是再试一次然后它运行良好。像魔术一样。

这可能解决问题,但是,打开另一种问题。并非所有情况都适用于此解决方案。我会解释一下:

我将分为两种类型的场景:

  1. 重试无法造成任何伤害 - 像SELECT或DELETE这样的操作。重试将具有相同的预期结果。所以,有了这类问题 - 我的解决方案工作正常!
  2. 插入或更新 - 重试会损坏信息。
  3. 我将重点关注数字2 。例如,假设我有:

    • 用户表。此表中的列:ID,UserName,Credits。
    • 存储过程使用户(按用户ID)支付部分学分。

    “付费”存储过程是:

    UPDATE tblUsers SET [Credits] -= @requestedCredits WHERE ID=@ID
    

    调用SP是一个棘手的问题:

    • 如果这没有问题 - 我们没事。
    • 如果失败,我们不知道操作是否在DB上完成。在此重试可能会导致用户支付两次

    所以,“重试”策略不是一种选择。

    我想到的解决方案:

    我想通过为每一行添加“VersionID”来解决这个问题。我的SP现在:

    UPDATE tblUsers SET [Credits] -= @requestedCredits, VersionId=NEWID() WHERE ID=@ID AND VersionID=@OldVersionId
    

    在让用户Pay()之前,我会检查VersionID(随机GUID),如果在付款后网络故障后这个GUID没有改变,我会再试一次(证明数据没有改变) DB)。如果此VersionId已更改,则用户将获得该服务的付款。

    问题是指我同时使用多台计算机时,这会使此解决方案出现问题。因为另一个实例可能对版本ID进行了Pay(),我认为我的更改是由我执行的(错误的)。

    怎么办?

2 个答案:

答案 0 :(得分:1)

听起来您正在从本地/内部部署/远程(即非Azure属性)到SQL Azure数据库进行SQL查询。

处理此问题的一些可能机制是

  • 带有API的Azure托管数据访问层

    考虑创建Azure WebApp或VM上托管的瘦数据访问层API,以便从远程计算机调用。此API服务可以可靠地与SQL Azure交互。

    SQL比HTTP端点对超时和网络问题更敏感。特别是如果您的查询涉及大量数据的传输。

  • 配置增加的超时

    问题中未指定C#应用程序使用的数据库访问机制。许多用于数据访问的库或函数允许您为连接指定增加的超时。

  • 虚拟专用网

    Azure允许您创建具有更好网络连接的站点到站点或点到站VPN。但是,这是最不优选的机制。

答案 1 :(得分:1)

你永远不会盲目地重试。如果出现错误,您读取当前状态,然后重新应用逻辑,然后写入新状态。 “适用逻辑”的含义因案例而异。再次使用表单呈现用户,刷新网页,在业务逻辑中运行方法,任何事情。

它的要点是你永远不能简单地重试操作,而不是首先重新加载持久状态。唯一的事实是DB中的内容,错误是警告您的缓存状态是陈旧的。