我如何才能确保我不会;t执行同一数据库事务两次
How can I ensure that I don't perform the same database transaction twice?
我正在通过网络对数据库执行插入操作,我想确保从不尝试插入已经插入的数据。客户端在web浏览器中运行,使用Javascript向服务器发送XMLHttpRequest,其中包含要插入的数据。如果出现错误,我必须稍后再试——例如,可能存在暂时的网络错误。然而,据我所知,我无法保证我会收到插入成功的通知,因为在请求到达服务器后,但在返回成功回复之前,网络可能会瘫痪。虽然这在我看来不太可能,但如果真的发生了,数据库会完全混乱,因为无法知道某些条目不应该存在。
使用插入的数据的存在或不存在,这样,如果出现第二个相同的事务,它就会被忽略。类似于:
INSERT MyTable (Value1, Value2, Value3)
SELECT @Value1, @Value2, @Value3
WHERE
NOT EXISTS (
SELECT *
FROM dbo.MyTable T
WHERE
T.Value1 = @Value1
AND T.Value2 = @Value2
)
;
请注意,这并不能完全解决两个客户端试图同时执行相同操作的潜在竞争条件——EXISTS
子句在INSERT
操作之前及时执行,这可能会导致两个客户端尝试插入。因此,您必须添加诸如WITH (UPDLOCK, HOLDLOCK)
之类的锁定(这对并发性来说很可怕,因为如果行不存在,它就必须使用范围锁定,这可以阻止不相关的数据插入),或者在客户端中适当地容忍关于重复密钥的错误。
如果只要客户端发送数据,数据就可以被复制,那么您可以通过以下几种方式来适应:
将其他列添加到表中,直到它是唯一的。
或者,创建一个作为事务一部分的时间戳/序列号,并在插入(在数据库事务中)后将该序列号记录到表中。将插入与缺少此序列号相关联。
为您的客户端开发一些策略,将已发送的请求保留到可以确认为止,这可能是一个额外的保护层,同时可以从一开始就防止一些重复尝试——如果您现在没有得到确认,但它稍后到达,则确认/删除排队的已发送事务。
为了将其推广到防止重复的DELETE
和UPDATE
,您应该添加rowversion类型的列。在所有查询的WHERE
子句中包含此值,如果自上次读取该行以来,其他人接触过该行,则这些查询将不会影响任何行。您仍然必须检测到没有任何行受到影响,然后再做一些明智的事情——这可能非常困难——但至少您已经检测到并避免了编辑冲突或重复操作。
如果问题不能孤立于对特定行的特定编辑,那么请提出一个新问题,提供一些具体的例子,以便您可以获得更好的建议。给我一个评论,并附上新问题的链接,我会看一看。
尝试为字段添加一些约束:
ALTER TABLE Persons ADD CONSTRAINT MyTable UNIQUE (Value1, Value2, Value3)
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 如何通过php页面将数据库值检索到jquery自动完成框中
- 使用javascript从数据库中添加表
- 通过CSV文件上载更新数据库表
- 平均值:无法将数据更新到数据库
- 电话间隙等待数据库事务完成
- 在 Phonegap 中的数据库事务语句之前发出警报触发
- Azure 自定义 API:执行数据库事务返回超时
- 如何使用 Node 从单个连接/事务进行多个数据库调用.js而且繁琐
- 如何在事务中创建索引数据库存储
- 处理错误后提交索引数据库事务
- 处理数据库事务返回
- 如何等待数据库事务完成它的操作并在phonegap中返回值
- Firebase事务不会更新Firebase数据库中的实际值
- 我如何才能确保我不会;t执行同一数据库事务两次
- HTML5数据库-事务VS executeSql回调顺序
- HTML5/js sqlite数据库不输入事务功能
- 使用web数据库的Phonegap错误:"表达式mydb的结果.事务不是一个函数
- Javascript数据库事务处理错误,无法准备没有列的语句
- 如何传递参数到PhoneGap数据库事务函数