Django、innodb 和行级锁定

0 投票
2 回答
924 浏览
提问于 2025-04-17 06:26

我有一个表格,里面有一些数据需要处理,还有一个工作程序会从这个表格中取出几条记录,处理完后再保存回去。处理完的记录会被标记为“已处理”。

现在我想同时运行多个这样的工作程序,但我需要确保两个工作程序不会同时处理同一行数据。所以我需要想办法来阻止这种情况发生。

我在使用django,按照我在MySQL手册上看到的,似乎可以实现行级锁定,但我找不到合适的例子来正确地做到这一点。唯一的例子说这个方法非常慢 :) http://djangosnippets.org/snippets/2039/

我可以再加一个字段,叫“锁定到”,这个字段会记录一个时间戳,表示在工作程序选中某行后,更新为现在时间加上X分钟。这样可以缩短锁定的时间(在选择后立即更新),并且可以防止其他工作程序选择这行数据,因为它会检查这个行是否被“锁定”,但在选择和更新之间的锁定问题仍然存在。

谢谢!

伊恩

2 个回答

-1

如果使用了锁,第二个工人就会一直等着,直到这个锁被释放。

你可以在开始处理之前,把条目标记为“这个条目的工作开始于[时间戳]”,然后让后续的工人忽略这些条目。接着,你可以设置一个定时任务,定期“释放”那些时间戳超过某个阈值但还没有标记为“完成”的条目,这样就能处理那些可能是工人崩溃或者其他问题导致的情况。

1

在MySQL中,存储数据主要有两种方式:MyISAM和InnoDB。它们各自有优缺点:

  1. InnoDB可以通过重放日志来从崩溃或意外关机中恢复。
  2. InnoDB可以在一种模式下运行,这种模式下可靠性较低,但在某些情况下性能更高。
  3. InnoDB会自动将多个同时插入的数据组合在一起,并同时写入磁盘。
  4. InnoDB在每次事务后都会刷新事务日志,这大大提高了可靠性。
  5. 与InnoDB不同,MyISAM内置了全文搜索功能。
  6. MyISAM在网络应用中仍然被广泛使用,因为在大多数数据库访问是读取的情况下,它通常被认为比InnoDB更快。
  7. 在向InnoDB表写入或更新数据时,只有特定的那一行会被锁定,而在MyISAM中,整个表都会被锁定。
  8. InnoDB支持完整的事务处理。

关于Django模型,它们默认支持创建MyISAM表。如果你需要表具有行级锁定,就需要使用InnoDB。这个页面是一个很好的起点:

它记录了一种方法,可以通过post_syncdb钩子动态发出ALTER SQL命令来更改表的存储引擎。(请注意,这篇文章是四年前写的,可能需要更新到当前版本的Django)。

你应该可以很简单地为你的模型添加元数据,指定每个表使用哪个存储引擎。然后你可以修改上面的例子,以根据这些元数据进行操作。

撰写回答