Mysql:从库出现system lock的根源揭秘
2023-09-05 15:00:16
MySQL从库System Lock:原因分析与解决方案
一、System Lock的根源
1. binlog格式选择
MySQL提供row和statement两种binlog格式。当采用row格式时,每个被修改的行都会被记录到binlog中。当从库执行row格式binlog时,它将逐行应用语句并对每个被修改的行进行行锁。若另一个会话试图修改同一个行,则会被阻塞,从而导致从库出现System Lock。
2. DML语句的影响
INSERT、UPDATE、DELETE等DML语句可能导致行锁或表锁。若一个DML语句在一个事务中执行,则它将持有行锁或表锁,直到事务提交或回滚。从库执行row格式binlog时,会逐行应用DML语句并对每个被修改的行进行行锁。此时,另一个会话若试图修改同一个行,则会被阻塞,导致System Lock。
3. DDL语句的处理方式
CREATE TABLE、ALTER TABLE等DDL语句可能导致表锁或数据库锁。若一个DDL语句在一个事务中执行,则它将持有表锁或数据库锁,直到事务提交或回滚。从库执行DDL语句时,会首先在本地执行,然后将语句记录到binlog中。当其他从库执行此binlog时,它们也会在本地执行。此时,若另一个会话试图访问同一个表,则会被阻塞,直到所有从库都执行完DDL语句,从而产生System Lock。
二、解决System Lock的策略
1. 合理选择binlog格式
若业务场景对数据一致性要求不高,则可使用statement格式binlog。这样,从库就不会出现System Lock问题。
2. 优化DML语句
尽量避免在一个事务中执行多个DML语句。若必须执行多个DML语句,应将它们分成多个小事务。这能降低从库出现System Lock的几率。
3. 优化DDL语句
尽量避免在高峰时段执行DDL语句。若必须在高峰时段执行DDL语句,应使用pt-online-schema-change等在线DDL工具。这能减少从库出现System Lock的几率。
代码示例:
# 使用statement格式binlog
mysql> SET GLOBAL binlog_format=STATEMENT;
# 分割DML语句为多个小事务
mysql> BEGIN TRANSACTION;
mysql> INSERT INTO table1 (col1) VALUES (1);
mysql> COMMIT;
mysql> BEGIN TRANSACTION;
mysql> UPDATE table1 SET col1 = 2 WHERE id = 1;
mysql> COMMIT;
# 使用pt-online-schema-change进行在线DDL
mysql> pt-online-schema-change D=db1,t=table1 -c 'ALTER TABLE table1 ADD COLUMN new_col INT NOT NULL;'
三、常见问题解答
1. 如何判断从库是否出现System Lock?
可以通过以下命令查看从库状态:
mysql> SHOW PROCESSLIST;
若出现System lock
或Waiting for table lock
,则表明从库出现了System Lock。
2. System Lock会导致哪些影响?
System Lock会导致从库无法进行任何写操作,影响业务正常运行。
3. System Lock是否可以自动恢复?
否,System Lock无法自动恢复,需要手动处理。
4. 如何快速修复System Lock?
可通过以下命令快速修复System Lock:
mysql> UNLOCK TABLES;
5. 如何预防System Lock?
遵循本文提到的策略,可以有效预防System Lock的发生。