在这种情况下可以观察到的行为不仅取决于数据库,还取决于 Web 应用程序的架构及其支持服务。
在评估此类情况时,重要的是要考虑多个因素 - 通常在使用浏览器中的 Web 应用程序的购物者和支持数据库之间至少有一个(通常是两个或多个)层。
如果我们从最简单的情况开始,(假设没有网络应用并且购物者直接连接到数据库)答案是是。 Oracle 的内部监视器和负责连接和断开连接的驱动程序非常擅长检测客户端何时因未提交的更改而断开连接并回滚。这是任何数据库服务器中的一个重要特性,因为许多客户端可能需要在短时间内更新相同的数据(例如在零售环境中购买商品),并且任何类型的丢失、无望、永久锁定数据都会严重破坏数据库提供并发数据访问的能力。我将在下面举一个例子来说明这一点,但是有大量的相关文档。概念手册中的Processes 有很多很好的相关信息。
假装我们没有网络应用程序,只是通过 sql plus 等连接。我们可以看到这个检测在起作用。
让我们创建一个测试表:
CREATE TABLE PRODUCT(PRODUCT_ID NUMBER,QUANTITY_REMAINING NUMBER);
Table created.
并给它一些记录:
INSERT INTO PRODUCT VALUES (1,100);
INSERT INTO PRODUCT VALUES (2,1);
COMMIT;
1 row created.
1 row created.
Commit complete.
现在让我们让不同用户启动两个会话。这两个会话都想购买项目 1。Session A 先到那里。
Session A:
UPDATE PRODUCT
SET QUANTITY_REMAINING = QUANTITY_REMAINING - 1
WHERE PRODUCT_ID = 1;
1 row updated.
然后,在Session A 意外退出之前,Session B 也尝试购买产品 1。她必须等到会话 A 完成。
Session B:
UPDATE PRODUCT
SET QUANTITY_REMAINING = QUANTITY_REMAINING - 1
WHERE PRODUCT_ID = 1;
注意这里没有“1 row updated.”。
现在我远程杀死Session A(本例中为pid 8771)它没有机会提交或回滚,也没有机会正常退出,断开连接等。
% kill -9 8771
zsh: killed sqlplus /nolog
现在Session A 不见了,但是如果我们查看会话 B,我们可以看到它立即能够继续:
1 row updated.
所以是的,Oracle 进程监控可以处理异常的客户端断开,就像正常的客户端断开并回滚一样。
但这只是故事的一小部分......在典型的 Web 应用程序中,由 Web 容器管理的连接池中存在(至少一个)非常长寿命的连接。对于数据库而言,无论连接的客户端是个人用户还是大型 Web 应用程序,它都可以同样处理意外断开连接。
但在 Web 应用程序中,用户无法控制 Web 应用程序的数据库连接 - 用户通过浏览器与 Web 应用程序进行交互,浏览器可能反过来对另一个正在与数据库通信的服务应用程序进行额外调用.浏览器中的用户不知道正在更新哪些数据或如何更新,只是想在购物车中放入一些东西。他们无法控制 Web 应用程序对其数据库连接的操作。
有了这些额外的部分,答案取决于应用程序架构和设计(而不是数据库)。通常,如果用户发送了将某些东西放入购物车(或完成订单)的请求,然后在收到回复之前意外断开连接,他们的请求仍然会由服务器完成,但他们不会在那里得到“好的”响应。
然后,应用程序开发人员(或 Web 框架)将决定如何处理可能无限期等待失踪购物者的购物车内商品(已成功保存到数据库中)。
许多应用程序开发人员(和 Web 框架)内置措施来帮助客户清楚地了解他们的请求状态(例如阻止选项卡或浏览器退出的弹出窗口,“你确定要丢失一个不完整的订单?”等)。或者将内置监视器以“回滚”已经在购物车中但一段时间后未实际购买的东西,或者将发送电子邮件以确认购买实际完成的时间(如果在单击“购买”后立即断电") 等等等等。但这取决于应用程序开发人员来决定。
总而言之,是的,Oracle 数据库可以在客户端断电等情况下检测到不完整的事务并很好地回滚。对于 Web 应用程序,可以使用不同的设计和技术来满足客户在不同时间失踪的不同需求,并提供易于理解和令人满意的用户体验。