我在2个表上运行更新查询(在MySQL 5.6中),如下所示:
UPDATE c_cache cc
JOIN p_cache pc USING (user_id, attribute_id, calculation_quarter)
JOIN batch_table bt USING (user_id, attribute_id, calculation_quarter, client_id, group_code, version_id)
SET cc.epop = SUBSTRING(bt.result, 1, 1),
cc.excl = SUBSTRING(bt.result, 2, 1),
cc.num_result = SUBSTRING(bt.result, 3, 20),
cc.status = 'FR',
pc.epop = IF(bt.enrolled = 2, SUBSTRING(bt.result, 1, 1), 1),
pc.excl = IF(bt.enrolled = 2, SUBSTRING(bt.result, 2, 1), 0),
pc.num_result = IF(bt.enrolled = 2, SUBSTRING(bt.result, 3, 20), REPEAT('0', 20)),
pc.status = IF(pc.status = 'FL2', 'S', 'FR');
p_cache
正在正确更新,但c_cache
中的3列设置为NULL,status
设置为'S'(这些列的所有默认值)。< / p>
错过的行通常是连续的(以块为单位)。
此查询位于存储过程的循环内,该存储过程一直运行直到p_cache
的所有'S'(陈旧)状态行标记为'FR'(新鲜),即计算。
(p_cache
的所有行都存在于c_cache
中,并且一一对应。)
batch_table
每次迭代以25000行的批量获取行,并通过一些存储的函数更新result
列中的计算结果。
这整个存储过程。从MySQL事件中调用。多个事件同时运行(每个事件用于一组独有的属性)以查找p_cache
中的过时行,并使用与此类似的查询批量更新两个具有计算结果的缓存表。
此异常行为仅发生在c_cache
,但有时仅发生。
架构定义是:
CREATE TABLE c_cache (
user_id INT(11) NOT NULL DEFAULT '0',
attribute_id INT(11) NOT NULL DEFAULT '0',
calculation_quarter DATE NOT NULL DEFAULT '0000-00-00',
version_id INT(11) NOT NULL DEFAULT '0',
epop TINYINT(1) DEFAULT NULL,
excl TINYINT(1) DEFAULT NULL,
num_result CHAR(20) DEFAULT NULL,
status ENUM('FR','S','FL1','FL2') NOT NULL DEFAULT 'S',
PRIMARY KEY (user_id, attribute_id, calculation_quarter, version_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE p_cache (
user_id INT(11) NOT NULL DEFAULT '0',
attribute_id INT(11) NOT NULL DEFAULT '0',
calculation_quarter DATE NOT NULL DEFAULT '0000-00-00',
client_id INT(11) NOT NULL DEFAULT '0',
group_code CHAR(5) NOT NULL DEFAULT '',
epop TINYINT(1) DEFAULT NULL,
excl TINYINT(1) DEFAULT NULL,
num_result CHAR(20) DEFAULT NULL,
status ENUM('FR','S','FL1','FL2','S1','S2') NOT NULL DEFAULT 'S',
PRIMARY KEY (user_id,attribute_id,calculation_quarter,client_id,group_code),
KEY date_status_id_index (calculation_quarter,status,attribute_id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
任何人都可以解释为什么会发生这种情况并建议一种避免这种情况的方法吗? 提前谢谢。