- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
使用 mysql 数据库在 node.js 中编写 API,我正在实现一个相当标准的模式:
If exists then update
else insert
这当然可以正常工作,直到同时向 api 发出多个请求,此时请求 2 上的 如果存在
可以在请求 1 的插入之前执行,从而导致两条记录而不是一条记录。
我知道处理这个问题的一种方法是确保数据库具有防止重复记录的约束或键,但在这种情况下,确定是否应该插入或更新的规则更加复杂,因此检查需要在代码中完成。
这听起来像是使用互斥锁/锁的好例子。我需要将其分发,因为 api 可能有多个实例作为池/场的一部分运行。
我提出了以下实现:
try {
await this.databaseConnection.knexRaw().raw(`SELECT GET_LOCK('lock1',10);`);
await this.databaseConnection.knexRaw().transaction(async (trx) => {
const existing = await this.findExisting(id);
if (existing) {
await this.update(myThing);
} else {
await this.insert(myThing);
}
});
} finally {
await this.databaseConnection.knexRaw().raw(`SELECT RELEASE_LOCK('lock1');`);
}
这一切似乎工作正常,我的测试现在只产生一个插入。虽然看起来有点暴力/手动。作为 mysql 和 node 的新手(我来自 c# 和 sql server 背景)这种方法是否合理?有更好的方法吗?
最佳答案
理智吗?主观。
技术上安全吗?它可能是 - GET_LOCK()
是可靠的 - 但不像你写的那样。
您忽略了 GET_LOCK()
的返回值,如果获得了锁,则返回 1;如果超时,您没有获得锁,则返回 0;在某些失败情况下,返回 NULL .
正如所写,您将等待 10 秒,然后无论如何都会完成工作,因此,不安全。
这假设您只有一个 MySQL 主服务器。如果你有多个大师或 Galera,它就不起作用,因为 Galera doesn't replicate GET_LOCK()
跨所有 Node 。 (Galera 集群是一个由可写主 Node 组成的高可用性 MySQL/MariaDB/Percona 集群,可同步复制,并且能够承受高达 (ceil(n/2) - 1) 的故障/隔离,其中 (ceil(n/2) - 1) em>n 个 Node )。
最好使用 SELECT ... FOR UPDATE
查找并锁定相关行。 ,它会锁定找到的行,或者在某些情况下锁定它们存在的间隙,阻止其他试图捕获相同锁的事务,直到您回滚或提交...但如果这不切实际,请使用 GET_LOCK()
是有效的,但要遵守上面关于返回值的观点。
关于MySql get_lock 用于并发安全更新插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56719410/
谁能分享一下GET_LOCK函数的使用实例? 示例函数: mysql> SELECT GET_LOCK('b',10); +------------------+ | GET_LOCK('b',10)
MySQL 版本 = 5.7.16 我需要自动处理数据库中的一些数据行。我有一个表的主键队列,以及应该协同工作的三段代码: 每十秒触发一次的事件,调用: 一个控制程序,它从队列表中选择单独的行,并将它
我需要一个数据库级别的同步。为此,我使用 GET_LOCK('prefix.some_id', 0)。在某些时刻,GET_LOCK 在不同主机上的不同脚本中为相同的 key 返回 1。可能是什么问题呢
使用 mysql 数据库在 node.js 中编写 API,我正在实现一个相当标准的模式: If exists then update else insert 这当然可以正常工作,直到同时向 api
这可能是一个非常愚蠢的问题,但我只是想知道如果你为 MySQL 设置自动提交,然后尝试获取锁,你是否必须在获取锁后提交才能保留锁? $mysqli->autocommit(FALSE); $q = '
我正在尝试使用 MariaDB 10.0.19 的 GET_LOCK() 功能来实现一个系统,该系统将事件调度程序运行的事件限制为一次只能运行一个。本质上,每个事件都会尝试获取“run_lock”,如
一个 mysql 服务器可以处理多少 GET_LOCKS - 整个服务器。我无法找到有关其局限性的任何信息。 最佳答案 根据 MySQL 文档 GET_LOCK()每个连接不能持有多个锁。 如上所说
有没有办法选择/显示所有当前使用GET_LOCK function 取出的锁? ? 请注意,GET_LOCK 锁不同于表锁,就像那些通过 LOCK TABLES 获得的锁一样 - 想知道如何查看那些的
MySQL的GET_LOCK(str,timeout)函数可用于实现应用程序锁或模拟记录锁。 如果我想等待无限秒,如何调用GET_LOCK? GET_LOCK('lock_name', -1) 有效吗
MySQL 中的 GET_LOCK() 接受负超时值,并解释为无限超时。 MySQL 文档: GET_LOCK() Tries to obtain a lock with a name given b
我的应用程序使用 Hibernate 作为 ORM。我正在尝试在我的应用程序中执行一些 mysql 锁定功能,例如 GET_LOCK、IS_FREE_LOCK、RELEASE_LOCK ( https
我发现在我正在开发的 Java 应用程序中使用了 MariaDB 的 GET_LOCK('lockname', 0)。 这里超时值设为0。我想它应该以非阻塞方式工作。但是,在日志文件中出现一些异常后,
场景很简单。我们有一个 PHP 脚本: 执行 MySQL 查询 GET_LOCK('TEST', 0) 睡了 5 秒 执行 MySQL 查询 RELEASE_LOCK('TEST') 打开网络浏览器并
我有自己的库 mylib,它使用 Boost 序列化库并动态链接它。现在我想将我的库链接到另一个代码 - 命令如下所示: /usr/bin/g++-8 -Wall -g -rdynamic CM
我是一名优秀的程序员,十分优秀!