我在具有 8GB RAM 的 Windows Server 2008 R2 计算机上使用 MySQL 5.1。
我每周更新 2 个数据库。两个数据库都由 MyISAM 表组成,我运行一个脚本,该脚本对某些表执行必要的 INSERT(无 UPDATE/DELETE)(下面的表 gp 有超过 370,000,000 行)。
在 mysql 脚本执行的某个时刻(整个过程大约需要 2.5 小时),我可以看到与 INSERT 同时运行的 SELECT 语句(但在不同的表上,甚至在不同的数据库中)被“阻止”并且一直挂起,直到整个插入过程完成。
一次插入将向 gp 表中插入大约 50-60 对整数,这可能需要长达 2-4 秒的时间(整个过程大约有 2000-4000 个整数)。因此,如果在 INSERT 期间有 10 个 SELECT,则所有这些 SELECT 都会排队,如下面的 SHOW PROCESSLIST 所示。
Id User Host db Command Time State Info
35 root localhost:36954 db Query 1 update INSERT INTO db_2.gp VALUES(@g,669313116),(@g,...),... (@g is an integer variable and there would normally be about 50-60 pairs of values here)
42 root localhost:38019 db Query 113 Sending data SELECT * FROM db.g WHERE ...
此 SHOW PROCESSLIST 已在本地脚本测试运行中运行,但在更新 LIVE 服务器上可以注意到相同的行为。我不知道为什么 SELECT 会被阻止(上面只有 1 个 SELECT,因为它源自本地主机,但在 LIVE 服务器上,可能有许多不同的 SELECT 从用户查询排队)。
在上面的进程列表中,可以看到 INSERT 正在数据库 db_2 中的 gp 表上执行,而 SELECT 语句正在针对数据库 db 中的 g 表运行。因此,它们是不同的表(并且位于不同的数据库中),所以我不明白为什么这里存在锁定问题。
有什么方法可以让 INSERT 不阻塞 SELECT 吗?请不要告诉我改用 InnoDB,因为我已经尝试过,网站速度明显变慢了。我需要继续使用 MyISAM。
答案1
在您给出的示例进程列表中, 并没有“阻塞” 。几乎可以肯定的是, 正在占用INSERT
大量I/O,导致 无法访问磁盘,无法完成将数据发送到客户端的任务。SELECT
INSERT
SELECT