MySQL 5中为表添加触发器时能否不锁定该表?大表不锁定添加触发器的可行性及合理性咨询
咱们来聊聊你问的MySQL 5里触发器和表锁定的问题,这确实是大表运维里容易纠结的点:
首先给你明确结论:完全不需要手动锁表。因为MySQL 5在执行CREATE TRIGGER或者DROP TRIGGER的时候,会自动给目标表加上排他锁(WRITE锁),直到整个语句执行完成。你现在写的手动锁表流程,其实是重复了数据库已经在做的事情。
那能不能做到完全不锁表就添加触发器?技术上是不可能的——触发器属于表的元数据,修改元数据时必须保证表的一致性,防止并发场景下出现表结构变更或者数据写入冲突,所以MySQL必须通过加锁来确保操作的原子性。
你担心大表加触发器会锁表影响业务,其实不用过度焦虑:触发器的创建是纯元数据操作,不会扫描、修改表中的任何数据,哪怕是几亿行的大表,CREATE TRIGGER的执行时间也通常是毫秒级的,锁表时间极短,对业务的影响几乎可以忽略。
反而你现在的手动锁表流程:
LOCK TABLES my_table WRITE; DROP TRIGGER IF EXISTS my_trigger; CREATE TRIGGER my_trigger AFTER UPDATE ON my_table FOR EACH ROW BEGIN ... END; UNLOCK TABLES;
才是更有问题的——它会人为拉长锁表时间。从LOCK TABLES到UNLOCK TABLES之间的所有操作(包括DROP、CREATE的时间,甚至你操作时的微小延迟)都会让表处于锁定状态,反而增加了业务阻塞的风险,属于没必要的操作。
直接去掉手动锁表的步骤,执行以下语句即可:
DROP TRIGGER IF EXISTS my_trigger; CREATE TRIGGER my_trigger AFTER UPDATE ON my_table FOR EACH ROW BEGIN ... END;
每个语句执行时会自动加锁,但总锁表时间是两个语句的执行时间之和,比手动锁表短得多,对大表的影响降到最低。
如果你的表是核心业务表(比如交易、订单表),对锁表时间极其敏感,建议选择在业务低峰期执行触发器的创建/修改操作,进一步降低影响。但从技术层面来说,只要不手动拉长锁表时间,给大表添加触发器是完全可行的,绝非“不明智的做法”。
内容的提问来源于stack exchange,提问作者Ben Ketteridge

