当MySQL服务器异常(慢)时,首先要考虑的是是否因为SQL语句导致数据库变慢。如果情况比较紧急,我们会立即显示完整的流程列表;去查看,但是我建议你以非交互的方式使用-e参数,因为这样你可以使用grep等命令来过滤结果,更方便直观的看到结果。1、抓SQL慢查询语句有两种方式:1、临时抓取SHOWFULLPROCESSLIST;#查看MySQL的运行线程;多执行几次,如果有相同的语句,可能是SQL慢查询语句;这个命令中最重要的是状态栏。mysql列出的状态主要有以下几种:Checkingtable#Checkingthedatatable(这是自动的)。Closingtables#表中修改的数据正在刷新到磁盘,已经用完的表正在关闭。这是一个快速操作,如果不是,则应检查磁盘空间是否已满或磁盘负载过重。ConnectOut#复制从服务器正在连接到主服务器。Copyingtotmptableondisk#由于临时结果集大于tmp_table_size,临时表正在从内存存储转换为磁盘存储,以节省内存。Creatingtmptable#创建一个临时表来存储一些查询结果。deletingfrommaintable#服务器正在执行多表删除的第一部分,刚刚删除了第一张表。deletingfromreferencetables#服务器正在执行多表删除的第二部分,正在删除其他表的记录。Flushingtables#ExecutingFLUSHTABLES,等待其他线程关闭数据表。Killed#向一个线程发送一个kill请求,那么这个线程会检查kill标志,同时放弃下一个kill请求。MySQL会在每个主循环中检查kill标志,但在某些情况下线程可能会在短时间后死亡。如果该线程被其他线程加锁,kill请求会在锁被释放时立即生效。被其他查询锁定#Locked。发送数据#正在处理SELECT查询的记录,并将结果发送给客户端。为组排序#SortingforGROUPBY。为订单排序#SortingforORDERBY。Openingtables#这个过程应该很快,除非被其他因素干扰。例如,在执行ALTERTABLE或LOCKTABLE语句之前,数据表不能被其他线程打开。试图打开一张桌子。Removingduplicates#ASELECTDISTINCTquery正在执行,但是MySQL无法在前一阶段优化那些重复的记录。因此,MySQL需要再次去除重复记录,然后将结果发送给客户端。reopentable#获取一张表的锁,但是必须在表结构修改后获取锁。已释放锁,关闭数据表,正在尝试重新打开数据表。Repairbysorting#修复指令是排序创建索引。Repairwithkeycache#修复指令是使用索引缓存一个一个地创建新的索引。它会比通过排序修复慢。Searchingrowsforupdate#正在查找符合条件的记录进行更新。它必须在UPDATE修改相关记录之前完成。Sleeping#等待客户端发送新的请求。系统锁#等待获取外部系统锁。如果你当前没有运行多个mysqld服务器同时请求同一个表,你可以通过添加--skip-external-locking参数来禁用外部系统锁。UpgradinglockINSERTDELAYED#Trying获取锁表以插入新记录。更新#是搜索匹配的记录,并修改它们。INSERTDELAYED#所有挂起的插入操作都已经处理完毕,正在等待新的请求。总结:一般一个简单的查询应该在2秒内完成。如果超时,可能会出现异常。另外,上面的大部分状态都是为了在出现问题后进行排查而提供的,类似于错误码;我在工作中,通常在配置文件中设置3个参数log-slow-queries=/data/3306/slow.log#慢查询日志路径,日志文件定义在my.cnflong_query_time=2#记录SQL查询语句longerthan2slog-queries-not-using-indexes=1#记录没有使用索引的sql通过以上3个参数,收集慢查询日志,编写脚本,mysqladmin截取日志,使用msyqlsla工具进行分析,然后每天8点执行预定任务,定期将结果通过邮件发送给公司DBA,或者自己,核心开发,抄送给CTO。2.我们遇到了慢查询,如何优化?创建索引explian命令#查看SQL语句使用索引SQL-no-cache\G,#查看SQL语句是否使用索引。注意里面有一个key,真正显示索引是否被使用。如果没有索引,则必须设置它。如何设置????比如我们查询当前系统的所有用户。这条查询语句启用PRIMARY主键索引(见key)mysql>explainselectuser,hostfrommysql.user\G******************************1.row******************************id:1select_type:SIMPLEtable:usertype:indexpossible_keys:NULLkey:PRIMARYkey_len:228ref:NULLrows:6Extra:usingindex1rowinset(0.00sec)查看表结构(RPI主键索引)mysql>descmysql.user;+-------------------------+----------------------------------+------+------+--------------------+--------+|Field|Type|Null|Key|Default|Extra|+----------------------+--------------------------------+------+-----+------------------------+------+|Host|char(60)|NO|PRI||||User|char(16)|NO|PRI|||三、如何创建索引?我们可以对where之后的条件的列进行索引,尽量选择大表上唯一值多的列作为索引,(比如性别列,唯一值很少,不适合做索引).如果条件列中的列数较多,唯一值很少,我们可以建立联合索引来达到优化的目的。联合索引有前缀特性,查询频率高的列应该放在最前面,不说细节。确定了如何创建索引之后,我们就开始创建索引1。创建索引有两种方式:altertablestudentchangeididintprimarykeyauto_increment;#增加自增主键索引altertablestudentaddindexindex_name(name)#增加公共索引createindexindex_deptonstudent(dept(8));#创建指定字符数的索引在数据量特别大的情况下,我们尽量选择数据库在低点或者选择晚上做,以免影响站点访问,紧急情况除外;4.更高级的优化,还可以使用selectprofile函数对SQL语句的每一个细节进行优化。遇到特别长的sql语句,优化空间不大。我会把sql语句送到核心开发去处理。比如一条语句很慢,我可以改成两条,分别去索引。它可能非常慢。高,也可用于改进产品,改进结构。比如这条语句没有优化空间,我们可以在内部从库上查询;
