【叶问】转自-》知数堂

叶问:https://mp.weixin.qq.com/mp/homepage?__biz=MzI1OTU2MDA4NQ==&hid=15&sn=8a530aa309c1fe6e4d99b3a0d49a9695&scene=1&devicetype=iOS11.0.2&version=1700032a&lang=zh_CN&nettype=WIFI&ascene=7&session_us=gh_7487b6ac717b&fontScale=100&wx_header=1

【1】、MySQL误删除frm文件该怎么办?

情况一:误删后还未重启MySQL
1、从proc中恢复.frm文件
cp /proc/`pidof mysqld`/fd/误删除的.frm /datadir/db/对应库的目录/

情况二:误删后也重启MySQL了
2、从备份中获取表结构
2.1 物理备份
从物理备份中直接把.frm文件拷贝回来。
2.2 逻辑备份
找到该表的DDL,在备用实例创建该表,再把.frm文件拷贝回来。

注意事项:
1、无论是情况一还是情况二,都需要重新设置属主和属组。
2、若恢复期间对该表执行了新的DDL,则上述方法可能都无效。
3、本案例在MySQL 5.7.18版本(开启表独立空间模式)下亲测通过。

【2】 MySQL的子查询有何问题,MySQL各个版本优化器针对子查询做了哪些改进?

以下只关于括号内子查询的情况(不涉及in/exists等情况):
一、MySQL5.5
1、子查询无法合并(针对括号内的子查询),优化器处理的逻辑是将数据加载到内存中形成视图,如select * from (select * from t1),因此MySQL5.5中子查询不能随便加括号
2、子查询结果集无法使用索引
3、可通过打开子查询改成join的方式优化

二、MySQL5.6
1、同MySQL5.5子查询同样不能合并
2、新增了auto_key特性,即会对被驱动的子查询结果集自动创建索引(适用于子查询结果集比较小且连接条件无索引的情况,因为需要在内存中创建索引,需要消耗cpu,tmp_table还有可能用到磁盘临时表,造成IO消耗)

三、MySQL5.7
1、支持简单视图合并,optimizer_switch新增derived_merge(如果被驱动表的结果集较少且没有索引就不利,如果被驱动表结果集较大且连接条件有索引就有利)
2、由于该特性,从MySQL5.6迁移到MySQL5.7子查询可能会出现性能下降,因此在数据库版本升级时需要特别注意

四、MySQL8.0
1、新增lateral特性
2、如SQL:
select * from t1 left join (select * from t2 group by c1) on t1.id=t2.id
可以改写为:
select * from t1 left join lateral(select * from t2 on t1.id=t2.id) t2 on t1.id=t2.id

更多知识点戳此:https://ke.qq.com/course/411889 

【3】如何降低UPDATE/DELETE时WHERE条件写错,或者压根没写WHERE条件带来的影响

0、尽量不要在线手工执行任何SQL命令,很容易出差错。线上直接执行SQL命令最好有第二检查人帮助确认
1、最好在测试环境执行SQL确认无误后,再到生产环境执行,或者提前在本地文本环境编辑好确认后再执行
2、建议打开sql_safe_updates选项,禁止没有WHERE条件或者不加LIMIT或者没有使用索引条件的UPDATE/DELETE命令被执行。

  也可以在用mysql客户端连接到服务器端时增加--safe-updates选项,

  例如:mysql --safe-updates -h xx -u xx

3、线上手动执行DML操作时,先开启事务模式,万一误操作可以回滚。例如:mysql> begin; update xxx; rollback; 4、通过DB管理平台执行DML操作,且在平台上增加对此类危险SQL的判断,直接拒绝危险SQL的执行 5、配置延迟从库,发现误删除数据后,从延迟从库快速恢复数据

【4】 MySQL常用的sql调优手段或工具有哪些

1、根据执行计划优化
   通常使用desc或explain,另外可以添加format=json来输出更详细的json格式的执行计划,主要注意点如下:
    1.1、type:显示关联类型。重点关注ALL(全表扫描)、index(全索引扫描);
    1.2、key_len:使用到索引的长度。通常该值大于30就要注意被选中的索引是否字符串类型,可否进一步优化;
    1.3、rows:预估扫描的行数。通常该值大于1万就要注意可否选择更合适的索引减少扫描的行数;
    1.4、extra:显示额外信息。重点关注Using temporary,Using filesort,尽量通过添加或调整来消除。

2、利用profiling优化
   通过探针的方式详细记录sql执行过程详细代价,可以很清楚地了解到sql到底慢在哪个环节。
   重点关注下列几种情况是否耗时较大:
   sending data
   creating sort index
   sorting result
   query end
   Waiting ... lock
   Creating tmp table
   Copying to tmp table

3、利用optimizer_trace优化
   可以输出优化器评估SQL执行计划的详细过程,尤其是每个可能的索引选择的代价。
   利用它可以明白优化器为什么选中索引A,而不选中索引B。

4、利用session status优化
   通过flush status重置session级别的状态值后,执行sql查看相应的状态变化量。
   可重点关注几个信息:
    Created_tmp_tables,创建内存临时表
    Created_tmp_disk_tables,创建磁盘临时表,尤其注意
    Handler_read_rnd,随机读
    Handler_read_rnd_next,全表扫描或者排序或者读下一行
    Select_scan,全表扫描
    Select_full_join,全表join
    Sort_merge_passes,多次归并排序

5、其他优化工具
    MySQL workbench、pt-query-digest等

【5】MySQL已启用了slow query log且long_query_time=0.01,为什么有些慢SQL还是没被记录呢?

1、在线动态设置long_query_time=0.01,但该设置对当前已建立的连接不会生效
2、log_slow_admin_statements=0,因此ALTER、CREATE INDEX、ANALYZE TABLE等操作即使超过long_query_time不会记录
3、min_examined_row_limit设置非0值,SQL检查行数未超过该值不会记录
4、slow log文件句柄发生了变化,如运行期间用vim打开log,最后又保存退出,此时文件句柄发生变化,需要执行flush slow logs5、误将slow_query_log_file当做slow log的开关,设置为1(此时slow log文件名为1)

【6】为什么long_query_time设置了1秒,slow log中还会记录小于1秒的慢查询?

可能原因如下:
1、设置了全局的long_query_time未对当前连接生效
2、打开了log_queries_not_using_indexes选项,记录了未走索引的SQL 
 
 
【7】MySQL中ANALYZE TABLE的作用是?生产上操作会有什么风险?
一、ANALYZE TABLE的作用
1、ANALYZE TABLE 会统计索引分布信息
2、对于 MyISAM 表,相当于执行了一次 myisamchk --analyze
3、支持 InnoDB、NDB、MyISAM 等存储引擎,但不支持视图(view4、执行 ANALYZE TABLE 时,会对表加上读锁(read lock)
5、该操作会记录binlog

二、生产上操作的风险
1、ANALYZE TABLE的需要扫描的page代价粗略估算公式:sample_pages * 索引数 * 表分区数
2、因此,索引数量较多,或者表分区数量较多时,执行ANALYZE TABLE可能会比较费时,要自己评估代价,并默认只在负载低谷时执行
3、特别提醒,如果某个表上当前有慢SQL,此时该表又执行ANALYZE TABLE,则该表后续的查询均会处于waiting for table flush的状态,严重的话会影响业务,因此执行前必须先检查有无慢查询

备注:上面多次提到MyISAM,仅是本次总结所需,并不推荐大家使用MyISAM引擎,使用InnoDB才是正道
原文地址:https://www.cnblogs.com/gered/p/10612761.html