【发布时间】:2021-05-24 12:04:11
【问题描述】:
- 下面的 SQL 在 MySQL 存储过程中。
- cron 作业每天在午夜运行一次以使用结果填充报告表的过程。
- 此过程大约需要 2 分钟才能运行。
- 请注意,
table1拥有数百万条记录。 - 我让它在午夜运行,因为白天有
INSERT/UPDATE交易,但不幸的是晚上也有一些交易。 - 当此过程运行时,如果有其他事务正在运行,则会在
table1上发生死锁错误。
我的问题是
- 为什么
SELECT语句导致table1死锁? - 在这种情况下如何避免死锁?
DROP report;
CREATE TABLE IF NOT EXISTS report AS (
SELECT
DISTINCT
companies.id company_id,
(
SELECT
SUM(`message_count`) single_phone
FROM
`table1`
WHERE
`table1`.`company_id` = companies.id
AND
`status` != 'error'
) AS single_phone,
(
SELECT
SUM(`message_count`)
FROM
`table1`
WHERE
`table1`.`company_id` = companies.id
AND
`status` != 'not error'
) AS log,
(
SELECT
SUM(`message_count`)
FROM
`table1`
WHERE
`table1`.`company_id` = companies.id
AND
`status` != 'error'
) AS log_monthly,
(
SELECT
SUM(`number_of_sms`) AS aggregate
FROM
`messages`
WHERE
`messages`.`company_id` = companies.id
) AS p_monthly
FROM
companies
INNER JOIN company_users ON companies.id = company_users.company_id
WHERE
company_users.confirmed = 1
AND
company_users.deleted_at IS NULL
);
【问题讨论】:
-
是什么让您确定这是死锁而不是任何其他类型的锁?您是否从 MySQL 服务器收到错误消息?服务器日志中有什么内容?
-
提示:您可以通过避免在顶级
SELECT中使用子查询来大大提高性能。相反,您可以在您JOIN的单个派生表中执行所有聚合。此外,您使用SELECT DISTINCT表明您有数据质量问题 - 像您这样的查询不应该使用SELECT DISTINCT。