当前位置: 首页 > 面试题库 >

数据库是否总是在查询或更新后锁定不存在的行?

魏煜祺
2023-03-14
问题内容

鉴于:

customer[id BIGINT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(30), count INT]

我想自动执行以下操作:更新客户(如果已经存在);否则,插入一个新客户。

从理论上讲,这听起来似乎非常适合SQL-
MERGE,
但是我正在使用的数据库不支持将AUTO_INCREMENT列与MERGE配合使用。

似乎表明,如果对不存在的行执行查询或更新语句,数据库将锁定索引,从而防止并发插入。

SQL标准可以保证这种行为吗?是否有任何数据库无法以这种方式运行?

更新 :对不起,我应该早先提到:解决方案必须使用READ_COMMITTED事务隔离, 除非
这是不可能的,在这种情况下,我将接受使用SERIALIZABLE。


问题答案:

回答我自己的问题,因为围绕该主题似乎有很多困惑。看起来:

-- BAD! DO NOT DO THIS! --
insert customer (email, count) 
select 'foo@example.com', 0
where not exists (
      select 1 from customer
      where email = 'foo@example.com'
)

对竞争条件开放。从我所能收集的资料来看,这个问题的唯一可移植的解决方案是:

  1. 选择一个要合并的键。这可以是主键,也可以是另一个唯一键,但是 必须 具有唯一约束。
  2. 尝试insert新的一行。您必须捕获如果该行已存在将发生的错误。
  3. 困难的部分结束了。在这一点上,可以确保该行存在,并且由于对它持有写锁定(由于insert上一步中的),因此可以保护您免受竞争条件的影响。
  4. 继续,update如果需要或使用select它的主键。


 类似资料:
  • 问题内容: 我使用下面的代码 来更新查询 使用。 但是我越来越。 我尝试搜索一些SO链接,建议关闭数据库,但是我再次遇到相同的错误。我已经提到我在代码中出现错误的地方。 问题答案: 通常,如果您同时进行多个查询(您没有完成一些早期的SQL语句,或者您打开了多个线程,或者您多次打开了数据库),就会得到此信息。 这段代码对和的使用有些混乱,(和缺少),这可能是问题的根源。 在《 SQLite C /

  • 问题内容: 我正在尝试制作简单的Java代码,以检查MySQL DB中是否存在表和/或列。我应该使用Java代码进行检查还是生成一个SQL查询字符串并执行以进行检查? 编辑- @ aleroot- 我尝试使用您的代码,如下所示。运行以下代码时,我看不到任何表或列。我只看到这个 我的数据库有很多数据库,表和列。我不知道为什么该程序可以正常工作。 问题答案: 要检查表是否存在,可以按以下方式使用Dat

  • 当页面第一次加载时,我需要检查中是否有图像,并加载最后一个图像。 否则,我禁用预览按钮,提醒用户按下新图像按钮,并创建一个空数组来放置图像; 问题是中的

  • 问题内容: 我正在编写一个使用本地SQL数据库存储数据的程序。 我正在使用在这里找到的驱动程序:https : //bitbucket.org/xerial/sqlite-jdbc 我试图从数据库中读取并将tableName的内容放入这样的JTable中: 然后,稍后我尝试返回并向表中添加一行: 然后,我想用新行更新之前创建的JTable。 但是,当我尝试添加行时会导致异常: 指向这一行: …在a

  • 问题内容: 将编辑后的数据保存在猫鼬中之前如何进行验证? 例如,如果数据库中已经存在,用户将收到某种错误,类似的错误,这是我的以下代码 问题答案: 通常,您可以使用猫鼬验证,但由于需要异步结果(对现有名称的db查询)并且验证器不支持promise(据我所知),因此需要创建自己的函数并传递回调。这是一个例子: 更新:更好的方法 前置钩似乎是停止保存的更自然的地方: 更新2:异步自定义验证器 看起来猫

  • 问题内容: 建立连接后是否可以检查(MySQL)数据库是否存在。 我知道如何检查数据库中是否存在表,但是我需要检查数据库是否存在。如果没有,我必须调用另一段代码来创建它并填充它。 我知道所有这些听起来都不太优雅-这是一个快速又肮脏的应用程序。 问题答案: 如果您只想知道数据库是否存在,以免在尝试创建数据库时出错,只需使用(From here):