mysql - 如何处理mysql中的并发访问?
问题描述
如果一个购物网站只有 1 种产品可用,而 2 人同时尝试购买,那么谁将获得该产品?服务器将如何优先考虑用户。“对亚马逊的闪购感到好奇,翻转卡丁车”。哪个算法?
解决方案
以下是幕后可能发生的事情,使用任何现代应用程序框架都很容易实现。
我假设您的情况是:
- 两个登录到您系统的用户说他们是
U1
并且U2
- 选择一个产品
- 只有一种产品可用
- 他们都点击了加入购物车/立即购买/结帐
- 将为一位用户提供服务,并通知另一位用户该产品不再可用
假设T1
和T2
是他们单击结帐按钮时的纳秒表示。T1
和T2
彼此相等的机会非常低,但有可能。
在您的情况下,网络服务器将在两个不同的线程中为用户生成的请求提供服务,TH1
并且TH2
. 这是极不可能的,因为在任何给定时间您的系统中都存在数百名用户,但假设您有多个内核,并且由 CPU 的两个不同内核提供服务TH1
并非不可能。TH2
因此,两者都TH1
将TH2
尝试抓住您的产品。
现在您需要在PRODUCT
:VERSION
和CHECKED_OUT
.
TH1
和都TH2
将同时启动它们自己的事务,比如TR1
和TR2
,假设你有 InnoDB 作为你的数据库引擎。
TR1
和都TR2
将:
PRODUCT
从数据库表中读取您的VERSION
和CHECKED_OUT
:{id: 1, version: 0, checked_out: 0, ...}
并将其传输到服务器。- 在服务器中,
TR1
和TR2
都将增加VERSION
之前读取的值并执行更新语句,说明UPDATE PRODUCT SET CHECKED_OUT = 1, VERSION = 1 WHERE ID = 1 AND VERSION = 0
- DB将锁定行,执行
UPDATE
并以顺序方式返回修改行的编号,因为UPDATE
应该在单个线程中执行。注意这里,这个线程是 DB 自己的线程,而不是TR1
andTR2
。 - 在这里,如果我假设之前,即
TR1
由DB 的线程提供服务,那么后面的业务逻辑将得到更新的行数等于 1,而更新的行数将得到 0。TH1
TR2
TH2
UPDATE
TR1
TR2
- 这反过来意味着
U1
可以检查产品,同时U2
会收到一条很好的道歉信息。
推荐阅读
- linux-kernel - 加载 eBPF 文件对象时如何解决“R0 invalid mem access 'inv'”错误
- assertion - 如何在junit中导入'org.hamcrest.collection'来测试收集方法
- typescript - 向 TypeScript 中的多个类添加重复逻辑?
- unity3d - Zenject Unity 测试场景 - 如何导航下一个场景,将容器正确更新到新的 SceneContext?
- php - SQL表中的PHP/SQL双下拉
- django - Apache2 服务器上的 PIL 模块 ImportError
- ruby-on-rails - 我可以在头部写一个静态资源链接吗?
- python - OSError: cannot identify image file <_io.BytesIO object at ...> 尝试使用 Keras 模型进行预测时
- loops - 如何在 Postman 中使用不同的客户对象数据循环 JSON 请求?
- java - 即使我输入错误的密码并且文件未保存在服务器上,我也总是得到 Server Response ok 200