温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Latch导致MySQL Crash

发布时间:2020-08-09 21:04:13 阅读:232 作者:沃趣科技 栏目:MySQL数据库
亿速云mysql数据库,读写分离,安全稳定,弹性扩容,低至0.3元/天!! 点击查看>>

沃趣科技高级数据库专家  董 红 禹

一、问题概述

最近我们遇到一个MySQL的问题,分析后很有代表意义,特地写出来供大家参考。 
出现问题是,数据库先是被置为只读,然后过了一段时间,MySQL直接Crash掉了 
发生Crash时MySQL的error日志中打印了以下内容:

		


	
	
		---------- 
	

	
		SEMAPHORES 
	

	
		---------- 
	

	
		OS WAIT ARRAY INFO: reservation count 1246555 
	

	
		--Thread 140363572082432 has waited at row0upd.cc line 2354 for 253.00 seconds the semaphore: 
	

	
		X-lock (wait_ex) on RW-latch at 0x7fa949340740 created in file buf0buf.cc line 1069 
	

	
		a writer (thread id 140363572082432) has reserved it in mode  wait exclusive 
	

	
		number of readers 1, waiters flag 1, lock_word: ffffffffffffffff 
	

	
		Last time read locked in file btr0sea.cc line 931 
	

	
		Last time write locked in file /export/home/pb2/build/sb_0-17068951-1447697721.44/mysql-5.6.28/storage/innobase/row/row0upd.cc line 2354 
	


根据日志中我们可以看到,线程140363572082432要对记录上一个X锁,但是等待0x7fa949340740线程的RW-latch的释放

我们在向下看查询到如下信息(涉及到用户信息 谓词就用xxx代替):

		


	
	
		173 lock struct(s), heap size 30248, 7925 row lock(s), undo log entries 7924 
	

	
		MySQL thread id 5709783, OS thread handle 0x7fa8f0da7700, query id 92213034 10.23.163.54 citicqyh updating 
	

	
		update TB_DEPARTMENT_INFO set TOTAL_USER=1 where ID='ac84f17e-82d3-4519-a1da-0d5a5a835d44' 
	

	
		---TRANSACTION 53065242, ACTIVE 313 sec fetching rows, thread declared inside InnoDB 2081 
	

	
		mysql tables in use 2, locked 0 
	

	
		MySQL thread id 5428690, OS thread handle 0x7fa8f0136700, query id 92213061 10.23.163.55 citicqyh Sending data 
	

	
		SELECT COUNT(DISTINCT r.user_id) FROM TB_DEPARTMENT_INFO d left join tb_qy_user_department_ref r on r.department_id = d.id WHERE d.org_id = 'xxx' AND (d.dept_full_name LIKE 'xxx%' or d.dept_full_name = 'xxx 
	

	
		Trx read view will not see trx with id >= xxx, sees < xxx 
	

	
		......还有很多select语句省略 
	


根据上面信息我们去数据库中查看了这些select语句,发现执行计划都是全表扫描。 
首先数据库变成了只读,最后数据库crash了,crash输出的信息如下:

		


	
	
		---------------------------- 
	

	
		END OF INNODB MONITOR OUTPUT 
	

	
		============================ 
	

	
		InnoDB: ###### Diagnostic info printed to the standard error stream 
	

	
		InnoDB: Error: semaphore wait has lasted > 600 seconds 
	

	
		InnoDB: We intentionally crash the server, because it appears to be hung. 
	

	
		 7fa8f9580700 InnoDB: Assertion failure in thread 140363714529024 in file srv0srv.cc line 1754 
	

	
		InnoDB: We intentionally generate a memory trap. 
	

	
		InnoDB: Submit a detailed bug report to http://bugs.mysql.com. 
	

	
		InnoDB: If you get repeated assertion failures or crashes, even 
	

	
		InnoDB: immediately after the mysqld startup, there may be 
	

	
		InnoDB: corruption in the InnoDB tablespace. Please refer to 
	

	
		InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html 
	

	
		InnoDB: about forcing recovery. 
	


InnoDB: Error: semaphore wait has lasted > 600 seconds 提示600秒没有响应 数据库选择了Crash 强制重启

从报错信息来看:

  1. update语句需要在记录上面加X锁,但是必须等待RW-Latch的释放
  2. 由于有大量的select语句是全表扫描,一直占用latch没有释放,update迟迟竞争不到RW-latch
  3. Innodb 的Diagnostic线程检查到RW-Latch等待超过了600秒还没有返回,认为系统出现了严重问题,于是触发了MySQL服务的Crash。

二、进一步分析

这里首先需要补充一下Latch的概念:Latch在MySQL中是用于保护高速缓冲区中共享数据的,举个例子: 
当我们执行select时,数据是缓存在buffer pool中的,多个线程并发访问或者修改这个数据必然需要一个并发控制机制,这个就是Latch

大家知道,数据库要访问的数据都必须先存在缓存中,而缓存一般比磁盘空间要小,数据缓存使用hash表来记录数据页是否在内存中。在Oracle中的并发控制比较精细:首先会对hash桶加latch,并根据hash桶查找对应的数据并加上pin,然后释放Latch。而MySQL相对没有控制得这么精细,对应的RW-Latch在errlog中说的很清楚,该RW-Latch是在buf0buf.cc的1069行创建的 
RW-latch at 0x7fa949340740 created in file buf0buf.cc line 1069

对应的代码摘录如下:

		


	
	
		rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING); 
	


跟踪源码,知道这个Latch是MySQL在数据库启动,初始化 innodb_buffer_pool时,将Latch创建好的。对应的函数调用过·程:

		


	
	
		buf_pool_init_instance()->buf_chunk_init()->buf_block_init() 
	


正是由于这个RW-Latch被长时间占用了,其他的线程一直竞争不到,才导致了这个问题

三、修复建议

这类问题的发生多数都是因为SQL写的不好,在表上面进行了大量的全表扫描占用了大量的Latch,解决方案就是避免SQL长时间占用latch:

  1. 修改select查询避免全表扫描,避免latch长期被占用
  2. 适当的加索引,让select执行更快,也避免一个select锁的数据更少
  3. 适当加大buffer pool instance,每个buffer pool都有自己独立的Latch,避免latch竞争。

亿速云「云数据库 MySQL」免部署即开即用,比自行安装部署数据库高出1倍以上的性能,双节点冗余防止单节点故障,数据自动定期备份随时恢复。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:http://blog.itpub.net/28218939/viewspace-2102421/

AI

开发者交流群×