【问题标题】:How can I prevent concurrency while writing and reading from my DB?如何在从我的数据库写入和读取时防止并发?
【发布时间】:2023-03-17 04:01:01
【问题描述】:

我也有一张包含用户登录信息和注册信息的表格。因此,当两个用户连续尝试添加他们的详细信息时:

  1. 写入冲突和表不会更新吗?

  2. 对这些写入使用线程是个坏主意。至于每次写入都会创建一个新线程,它会阻塞服务器。服务器自己负责管理吗?

  3. 锁定表是个好主意吗?

我的后端在 PHP/Apache 上运行,数据库使用 MySQL (InnoDB)。

【问题讨论】:

  • 这个问题提出了一个在现实中不存在的假设问题。
  • 为什么锁定不是一个真正的问题?仅仅因为建立关系数据库来回答这个问题并不意味着它不是一个真正的基本问题。这只是意味着已经有了答案,OP 不需要采取任何进一步的行动。

标签: php mysql concurrency innodb backend


【解决方案1】:

关系数据库旨在避免此类情况。除非您从头开始设计自己的关系数据库,否则您无需担心它们。

简而言之,只要知道这一点:任何时候启动写入,都会有一个行级锁。如果另一个事务想要写入同一行,那么它必须等到第一个事务释放锁。这是关系数据库的基本部分。你不需要加锁,因为他们已经想到了:)

您可以阅读更多关于 MySQL 如何执行锁以避免死锁和其他事务错误here

【讨论】:

    【解决方案2】:

    如果您对此非常怀疑,或者您在注册用户时可能正在做多件事情并且需要原子地完成它们,那么您可能想看看在 MySQL 中使用 Transactions。这里有一篇关于交易的不错的文章http://www.mysqltutorial.org/mysql-transaction.aspx

    【讨论】:

      【解决方案3】:
      BEGIN;
      do related reads/writes to the data
      COMMIT;
      

      在该“事务”中,连接会看到一致的数据视图,并阻止其他人干扰该视图。

      也有例外。主要的是

      BEGIN
      SELECT ... FOR UPDATE;
      fiddle with the values SELECTed
      UPDATE ...;  -- and change those values
      COMMIT;
      

      SELECT .. FOR UPDATE 宣布不应篡改的内容。如果另一个连接想弄乱相同的行,它必须等到您的COMMIT,此时他可能会发现情况发生了变化,他需要做一些不同的事情。但是,一般来说,这避免了“死锁”,即两个事务严重地相互踩踏,以至于一个事务必须“回滚”。

      使用这样的技术,“并发”只能短暂且相对精确地被阻止。也就是说,如果两个连接使用 不同 行,both 可以继续 - 不需要“防止并发”。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-21
        相关资源
        最近更新 更多