锁定mySQL表/行

Mil*_*uzz 5 mysql

有人可以解释在mysql中锁定表和/或行的必要性吗?

我假设它阻止多次写入同一个字段,这是最佳做法吗?

reg*_*ero 3

首先让我们看一个好的文档这不是一个mysql相关的文档,它是关于postgreSQl的,但它是我读过的关于事务的更简单和清晰的文档之一。阅读此链接后,您将更好地理解 MySQl 事务http://www.postgresql.org/docs/8.4/static/mvcc.html

当您运行事务时,将应用 4 条规则 (ACID):

  • 原子性:全有或全无(回滚)
  • 连贯性:前连贯、后连贯
  • 隔离:不受他人影响?
  • 持久性:承诺,如果完成了,就真的完成了

在这些规则中,只有一个是有问题的,那就是隔离。使用事务并不能确保完美的隔离级别。前面的链接将更好地向您解释什么是幻读以及并发事务之间的隔离问题。但为了简单起见,您应该真正使用行级别锁来防止与您同时运行(并且可能在您之前提交)的其他事务更改相同的记录。但是锁带来了死锁......

然后,当您尝试使用带锁的良好事务时,您需要处理死锁,并且需要处理事务可能失败并应该重新启动的事实(简单的 for 或 while 循环)。

编辑: - - - - - -

InnoDb 的最新版本提供了比以前版本更高级别的隔离。我已经做了一些测试,我必须承认,即使是应该发生的幻读现在也很难重现。

MySQL 默认处于 PosgtreSQL 文档中解释的 4 个隔离级别中的第 3 级(其中 postgreSQL 默认处于第 2 级)。这是可重复读取。这意味着您不会出现脏读,也不会出现不可重复读。因此,修改您在事务中进行选择的行的人将获得隐式锁定(就像您执行了选择更新一样)。

警告:如果您使用旧版本的 MySQL(例如 5.0),您可能处于级别 2,则需要使用“FOR UPDATE”字样执行行锁定!

我们总能找到一些很好的竞争条件,使用聚合查询,如果您不希望人们在您添加行时处于第四级隔离(通过在查询末尾使用锁定共享模式)可能会更安全。正在执行一些任务。我已经能够重现一个可序列化级别的问题,但我不会在这里解释复杂的示例,非常棘手的竞争条件。有一个非常好的竞争条件示例,即使可序列化级别也无法修复:http://www.postgresql.org/docs/8.4/static/transaction-iso.html#MVCC-SERIALIZABILITY

在处理事务时,更重要的是:

  • 事务中使用的数据必须始终在事务内部读取(如果您在 BEGIN 之前有数据,请重新读取它)
  • 理解为什么高隔离级别设置隐式锁并可能阻止一些其他查询(并使它们超时)
  • 尝试避免死锁(尝试以相同的顺序锁定表)但处理它们(重试被 MySQL 中止的事务)
  • 当您的应用程序代码假设没有插入或更新应该修改他正在使用的数据集时,尝试使用序列化隔离级别(锁定共享模式)冻结重要的源表(如果不是,您不会遇到问题,但您的结果将忽略并发更改)