RAID卡:
bbu force wb
内核:
1. io调度 deadline noop
2. vm 管理 vm.swappiness = 0
文件系统 mount nobarrier data=ordered writeback
1. 加大队列 nr_requests
2. 关闭numa
CPU:
innodb_read_io_threads = cpu核心数/2
innodb_write_io_threads = cpu核心数/2
read + write = cpu核心数
可以根据读写比例调整上述值
磁盘:
innodb_io_capacity = 硬盘的iops
脏页刷新:
当超过innodb_max_dirty_pages_pct的设定值 , 会将innodb_buffer_pool刷新到磁盘
重做日志ib_logfile写满后
机器空闲的时候
当写操作很频繁的时候,重做日志ib_logfile切换次数就会很频繁,只要有一个写满了,就会将脏页大量的刷入磁盘,这会对系统系统有整体的影响。为了避免过大的磁盘io , innodb_adaptive_flushing会自适应刷新。参数默认开启。
innodb_buffer_pool:
1. innodb_buffer_poll有2个区域,sublist of new blocks(热数据) sublist of old blocks(不经常访问的数据)
用户访问数据,如果缓冲区中有相应的数据,则返回,如果没有,从磁盘空间读入sublist of old blocks区域,然后再移动到2. sublist of new blocks 区域,然后在根据LRU算法将最近最少使用的数据移除旧数据页
3. 但是这其中也有一些问题,假如有些语句做统计用全表扫描,或者做一次mysqldump,这时就会进入sublist of new blocks区域,把一些真正的热数据提走,这样会造成缓冲区的进进出出,导致磁盘io繁忙
4. innodb_old_block_pec参数可以控制进入缓冲区sublist of old blocks的数量,默认37,占整个缓冲区的3/8。当全表扫描一个大表或者做mysqldump可以将innodb_old_block_pec设置的小些使数据块少量的进入缓冲区,从而让更多的热数据不被踢出。
Old database pages 23600 在旧区域存放多少页
pages made young 411111, not young 2987612 移动到新区域多少页 / 没有移动的有多少页
1274 youngs/s 16521 non-youngs/s
如果你没有全表扫描,发现youngs/s值很小,那么就该增大innodb_old_blocks_pec或者减少innodb_old_blocks_time 。如果进行了全表扫描,发现non-youngs/s的值很小,那么就应该增大innodb_old_blocks_time
innodb数据恢复时间:
依赖于 buffer poll ,脏页面比例,tps等因素
innodb_buffer_pool_instances = 10 innodb_buffer_poll实例的个数
最多支持64 。 innodb_buffer_pool_size 必须大于1G
innodb_buffer_pool_dump_at_shutdown = 1
关闭mysql时,把热数据dump到本地硬盘
innodb_buffer_pool_dump_now = 1
采用手工方式把数据dump到磁盘
innodb_buffer_pool_load_at_startup = 1
在启动时把热数据load到内存
innodb_buffer_pool_load_now = 1
采用手工方式把热数据load到内存
慢日志:
当数据库连接数很高时,此时需要注意,可以通过cacti监控软件观察时间点,然后把这一段时间点的慢日志截取出来
sed -n '/#Time:110720 16:17:20/,/end/p' mysql.slow > slow.log
然后用mysqldumpslow 命令取出最耗时的最长的10条慢sql进行分析
mysqldumpslow -s t -t 10 slow.log
主从同步 :
slave_exec_mode参数可自动处理同步复制错误
set global slave_exec_mode='IDEMPOTENT'
默认值是 STRICT 严格模式
设置完毕后,当出现1023(记录没有找到) , 1026(主键复制)时,会自动跳过错误,并且记录到错误日志中。
如果从库某几张表的数据和主库不一致,解决方法:
1. 停止slave
2. 在主库上导出这几张表,并记录下同步的binlog时间点和pos点
mysqldump -uroot -pxxx -q --single-transation --master-data=2 yourdb table1 table2 > xxxx.sql
3. 导入sql文件到从库。找出备份的sql文件中的binlog和pos点
4. change master
直到sql_thread线程为NO,这期间同步报错可以一律跳过
stop slave ; set global sql_slave_skip_counter=1 ; start slave;
如何干净的清除slave的同步信息
stop slave ; reset slave 不行。 要使用 reset slave all;
主从切换:
事件调度器在主从切换出现的问题:
set global event_scheduler = 1;
在主从架构中 event只能在主上触发,在slave上不能被触发,如果再slave上触发了,同步就会坏掉。
show event
status :slaveside_disabled
需要执行 alter event 'insert' enable
人工误删除innodb ibdata 数据文件,如何恢复:
先找到mysqld进程的pid netstat -nlp | grep mysqld 这里是30246
执行 ll /proc/30426/fd | grep 'ib_|ibdata'
关闭前端业务 ,执行 flush tables with read lock
set global innodb_max_dirty_pages_pct=0; 让脏页尽快刷新到磁盘
show engine innodb status\G;查看innodb状态信息,确保脏页已经刷新到磁盘 。
复制文件到mysql的数据目录 。重启mysql
where 从句中的in 子查询 :
select * from tables1 where filed in (select filed from table2 where cacheld='xxxx')
工作原理:mysql先要为内层的查询语句查询结果建立一个临时表,然后外层查询语句才能在临时表中查询记录,查询完成后,还需要撤销这些临时表。
sql优化案例分析 :
1. not in 子查询优化
在生产环境中 ,尽量避免子查询,可以用表连接取代。 (select update delete )
2. 模糊匹配 like '%xxx%'优化
不要使用select * , select * 无法覆盖索引。
select 字段必须存在索引。
3. limit 分页优化
select xx,xx,xx from logdb order by id limit 9999,10;
select xx,xx,xx from logdb where id >=10000 order by id limit 10
4. count(*) 统计如何加快速度
count(*)如果数据量大一般都是比较慢的
select count(*) from L_user;
走聚集索引,innodb聚集索引就是数据,需要全表扫描统计。
select count(*) from L_user where Sid >=0;
如果加条件,走where后的Sid辅助索引,辅助索引不存放数据,而是由一个指针指向对应的数据块。统计时消耗的资源少,速度也更快。
虽然上述方法加快了速度,类似统计的sql语句 select count(*) select sum() 。这不建议在主库执行,会导致锁表。不走索引,表锁。
5. or 条件优化
select * from USER where name='bob' or age='30';
这条语句是不会走索引的。全表扫描。
select * from USER where name='bob' union all select * from USER where age='30'
##############################################################################
6. 不必要的排序
select count(1) as rs_count from
(
select a.id,a.title,a.content,b.log_time,b.name
from a b
where a.content like 'rc_%' and a.id=b.id
order by a.title desc
)
as rs_table;
select count(1) as rs_count from
(
select a.id from a join b
on a.id = b.id and a.content like 'rc_%'
)
as rs_table
7. 不必要的嵌套 select 子查询
select count(1) as rs_count from
(
select a.id,a.title,a.content,b.log_time,b.name
from a b
where a.content like 'rc_%' and a.id=b.id
order by a.title desc
)
as rs_table;
select a.id,a.title,a.content,b.log_time,b.name
from a join b
on a.id = b.id and a.content like 'rc_%'
order by a.title
#########################################################################################################
10.用where代替having
这个简单,就不举例子了