返回

Mysql:从库出现system lock的根源揭秘

后端

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 lockWaiting 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的发生。