软件:Django 2.1.0,Python 3.7.1,MariaDB 10.3.8,Linux Ubuntu 18LTS
我们最近在新应用程序中添加了一些负载,并开始观察到许多死锁。经过大量挖掘后,我发现Django select_for_update查询导致带有多个子查询(3或4)的SQL。到目前为止,在所有僵局中,至少有一个事务涉及带有多个子查询的此SQL。
我的问题是... select_for_udpate锁定每个涉及的表中的记录吗?就我而言,是否会锁定主SELECT以及子查询所使用的其他表中的记录?还是仅来自主SELECT的记录?
来自Django文档:
默认情况下,select_for_update()锁定查询选择的所有行。例如,除了查询集模型的行之外,在select_related()中指定的相关对象的行也被锁定。
但是,我没有使用select_related(),至少我没有明确指出它。
我的应用程序摘要:
with transaction.atomic():
ModelName.objects.select_for_update().filter(...)
...
update record that is locked
...
大量阅读后,我做了以下尝试来控制死锁:
1-尝试/捕获异常错误“ 1213”(死锁)。发生这种情况时,请等待30秒,然后重试查询。在这里,我依靠数据库引擎的ROLLBACK函数。 同样,显示SHOW ENGINE INNODB STATUS和SHOW PROCESSLIST的输出。但是SHOW PROCESSLIST没有提供有用的信息。
2-修改Django select_on_update,使其不使用子查询构建SQL。现在,生成的SQL包含一个带有值且没有子查询的WHERE。
还有什么可以减少死锁的事情?