DBA技能
主备
启动slave thread:登录到sql后运行start slave;
查看主备:show slave status\G
主备切换
发生切换的原因是ha在固定时间内来测试数据库能否访问,如果数据库在多长时间内一直不能访问才会发生主备切换
所以主备切换的原因是一定时间内数据库无法访问,原因可能有qps过大或慢sql rt过高导致数据库堵住,或线程池满数据库无法访问,连接满拒绝访问
数据
1.max_connections:允许所有用户的最大连接数,包括root除了(‘root’@‘127.0.0.1’和’root’@’localhost’),满了报错too many connections,错误号1040
2.max_user_connections:单个用户允许的最大连接数,包括root除了(‘root’@‘127.0.0.1’和’root’@’localhost’),满了报错User root already has more than 'max_user_connections' active connections,错误号1203
3.数据库线程池:32 thread_pool_size=32,thread_pool_oversubscribe=10;线程池大小为32*(10+1)=352,加上其它后台线程也不过400
指标解读
rt:通过调用tcprstat来监控MySQL的响应时间,单位us,rt高就是mysql的响应时间高,就是有慢sql
load average:是 CPU的Load,它所包含的信息不是CPU的使用率状况,而是在一段时间内CPU正在处理以及等待CPU处理的进程数之和的统计信息,
也就是CPU使用队列的长度的统计信息。Load Average却从另一个角度来展现对于CPU使用状态的描述,
Load Average越高说明对于CPU资源的竞争越激烈,CPU资源比较短缺,因为cpu执行快io执行慢,load高一般是有执行慢的io操作使得cpu等待。
Load Average是与机器内核数有关的。以一个单核的机器为例,load=0.5表示CPU还有一半的资源可以处理其他的线程请求,load=1表示CPU所有的资源都在处理请求,没有剩余的资源可以利用了,而load=2则表示CPU已经超负荷运作,另外还有一倍的线程正在等待处理。所以,对于单核机器来说,理想状态下,Load Average要小于1。同理,对于双核处理器来说,Load Average要小于2。结论是:多核处理器中,你的Load Average不应该高于处理器核心的总数量。
cpu利用率:是对一个时间段内CPU使用状况的统计,通过这个指标可以看出在某一个时间段内CPU被占用的情况
qps:每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准
tps:Transactions Per Second(每秒传输的事物处理个数)
即服务器每秒处理的事务数。TPS包括一条消息入和一条消息出,加上一次用户数据库访问。(业务TPS = CAPS × 每个呼叫平均TPS)
TPS是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。
加权限
磁盘满了:
很可能是备份进程,ps -aux |grep xtra查看
df -h查看磁盘占用
sudo du -sh /u01/* 查看占用详情
查看最大的库最大的表
sudo du -sh /u01/my*:查看哪个实例最大
cd /u01/my3306/data:
sudo du -sh xxx* |grep G|sort:查看以xxx开头并是G体量的并从小到大排序
sudo du -sh *.ibd |grep G|sort:查看.ibd结尾的表文件以GB为体量的大小并从小到大排序
sudo du -sh *.ibd |grep G|wc -l:查看文件个数
锁表 5.6.16.6库
索引有关
fulltext index会锁表
字段有关
加AUTO_INCREMENT列
加列中有隐式的NOT NULL转换时候 (主键列 就算没有指定not null 也会加上这个属性的)
修改列的数据类型。(扩大长度没问题(但是varchar长度过大会造成锁表,因为长度过大会自动将varchar转换成text),修改数据类型就会锁表varchar到text也算是修改数据类型也会锁表,int到bigint也会锁表,只有修改varchar(1) 到varchar(10)这种扩大长度的才不会锁表)
其他
删除PrimaryKey
转换/修改字符集
锁表时间
2G的表大约锁表几秒钟,主要由IO等资源决定,时间不确定
mysql online DDL锁
1.,lock=none :支持select和DML在线无锁变更
2.,lock=shared :支持select 不支持DML
3.,lock=exclusive :不支持select 不支持DML
4.,lock=default : mysql自己选择锁定资源最少的方式
数据库设计
1.表设计
1) 表必须定义主键,主键建议为整型
2) 禁止使用外键
3) 多表中的相同列,必须保证列定义一致
4) 表默认使用InnoDB,表字符集使用utf8
5) 表必须包含gmt_create和gmt_modify字段,即表必须包含记录创建时间和修改时间的字段
6) 单表数据量超过500w或数据容量超过10G考虑分表
2.字段设计
1) 表被索引列必须定义为not null,并设置default值
2) 禁止使用float、double类型,建议使用decimal替代
3) 禁止使用blob、text类型保留大文本、文件、图片,建议使用其他方式存储(TFS),MySQL只保存指针信息
3.其他
1) 禁止使用:存储过程、触发器、函数、视图、事件等MySQL高级功能
2) 禁止使用跨库查询
3) 禁止使用子查询,建议将子查询转换成关联查询
4) 禁止核心业务流程SQL包含:计算操作、多表关联、表遍历case when等复杂查询,建议拆分成单表简单查询
解析log命令
mysqlbinlog -v --base64-output=decode-rows -d 数据库名字 log名字 > /tmp/mysql-bin.000004.sql
eg:
mysqlbinlog -v --base64-output=decode-rows -d seotools mysql-bin.000004 > /tmp/mysql-bin.000004.sql
mysqlbinlog -v --base64-output=decode-rows --start-position=442183506 --stop-position=453224675 mysql-bin.000970 >>zjk.log
恢复删除数据
rollback
跳过错误,登录mysql,其实是跳过一个事务
stop slave;
set global sql_slave_skip_counter=1;
start slave;
smart,登录mysql
stop slave;
set global slave_exec_mode='smart';
start slave;
stop slave;
set global slave_exec_mode='strict';
start slave;
数据回滚——udc>数据质量>数据回滚
删除/修改数据查询(解析binlog)——udc>数据质量>数据轨迹
解binlog
mysqlbinlog --help
高低水位限流
1.为threads_running设置一个硬上线,当并发超过此值是,拒绝执行sql,保护MySQL,我们将这个称之为:高水位限流
2.为mysql server层并发运行线程数目设置一个软上线,当超过此值时,线程自动按照FIFO顺序排队,将并发运行线程控制在一定数目之内,减少context switch及大量线程之间可能的锁竞争,使 MySQL性能能够稳定在较高点,我们将这个称之为:低水位优化
主要参数包括2个:show variables like "threads_running%";
threads_running_low_watermark
threads_running_high_watermark
当系统变量threads_running超过threads_running_low_watermark设置的阀值时,线程进行排队;
超过threads_running_high_watermark设置的值时,直接拒绝该SQL。
建议设置:
threads_running_high_watermark为1000,threads_running_low_watermark作用不大。
注意:5.6版本启用了线程池,线程池对请求做了排队,因此一般情况下,无需再设置高低水位。
对于thread_pool_size=32,thread_pool_oversubscribe=10的设置,处理请求的线程只有:
32*(10+1)=352,加上其它后台线程也不过400,因此threads_running不会达到很高,
遇到极端情况,线程池满负荷运转,但rt已经不满足需求,可以考虑将threads_running_high_watermark
设置的更小。
sql限流
查看show variables like 'sql%filter%';
查看sql_delete_filter sql_select_filter sql_update_filter是否限流
如何限流参考:https://askdba.alibaba-inc.com/libary/control/getArticle.do?articleId=11632
可以指定带有某些字段的select/insert/delete的SQL并发数,超出并发数的查询报错:Query execution was interrupted
启动/关闭实例
my3361
myadm -P3361 -d startup/shutdown/startslave:启动关闭3361实例,或者启动3361的备份进程
myadm startup/shutdown/startslave:启动或者关闭这台机器上的所有实例,或者启动这台机器上的所有备份进程
实例挂了
报警:slave io/sql thread error 或 slave] failed
1.尝试12中的启动实例
2.启动不成功查看alert日志:/u02/my3306/log/alert.log
重搭备库
数据迁移
数据迁移分为如下几种种情况
1.迁移数据表,且表没有很多的写入,表中数据不算太大
2.迁移整个库且没有太大的写入
待添加
3.迁移整个实例,且没有太大的写入
待添加
4.不管迁移什么,但是有很多的写入
这时候需要全量迁移还要增量迁移,用DTS或者精卫,要在一个写入少的时间里做个切换
筛选连接并kill掉
select concat("kill ", id, ";") from information_schema.processlist where user = 'tbdw';
数据库升级 说白了就是实例迁移,但需要开发升级相应依赖
msyql 5.6 tddl 5 jdbc 5.1.18
实例迁移,扩容,都是一样的
慢sql日志
/u02/my3306/log/slow_history/
字符转换
ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8;
查看用户连接数thread_connected
/opt/dbfree-minion/data/ grep threads_connected metric.21.10.2016 | grep 3306 找到对应的时间点的位置
或者查看thread_connected指标
drop table
有风险,严重消耗IO,还会对table cache加锁,所有的操作都会阻塞,
经历两个步骤:1.flush dirty data:删除buffer pool上的数据,会加table_cache的锁,其他查询去不无法执行,2.remove data file:删除物理文件
1.drop table操作需要进行sleep操作,sleep 60,不是解决阻塞,而是缓解
2.对于大表一定建立文件硬连接,缩短第二部的耗时
1、建立硬链接。
ln table.ibd table.idb.hdlk
2、mysql执行drop table操作。(实际上这一步只是删除指向文件的指针)
drop table if exists tablename;
3、使用truncate删除物理文件。(这里才是真正的删除数据)
truncate -s xxxG filename
删除数据
ssh能登陆ping不通
交换机故障,此时应用没问题,不需要做什么
ssh不能登陆能ping通
RSA/raid卡故障,此时应用其实不能用了,相当于挂了
分配实例
按照 qps计算实例的buffer pool, 取最近15天qps的最大值,如果qps<100, bp=1G; 100<=qps<=1000, bp=10G; 1000<=qps<=2000, bp=35G, qps>2000,保持原来的bp
网卡
千兆网卡:1000Mb 平时说的网络发送接收之类的单位都是MB,换算单位是1000/8=125,但是网卡是双网卡对,所以瓶颈是250左右
动态指定索引(索引存在,但走不到,应用加force index来不及的情景)
语法
Set global sql_hints='+,<schema_name>,<table_name>,<index_name>,<keyword1>~<keyword2>…';
eg:select id from test.heartbeat where a=xxx and b=xxx
set global sql_hints ='+,test,heartbeat,idx_id,select id from~a=~b=';
分表支持,例如heartbeat表是分表
set global sql_hints ='+,test,heartbeat_,idx_id,select id from~a=~b=';
无法支持分库,想要分库必须手动每个分库上都添加
查看规则
show sql_hints;
移除规则
set global sql_hints=='-,idx_id';
清理所有规则
set global reset_all_sql_hints=1
批量删除大量慢sql
select concat("kill ", id , ";") from information_schema.processlist where time > 10 into outfile 'kill.sql'
source /u01/my3306/data/kill.sql
开启全量sql
source /home/mysql/.bash_profile
for sockets in `ps -ef|grep mysqld|awk -F "--socket=" '{print $2}'|awk '{print $1}'`;
do
mysql -uroot -S $sockets -e"uninstall plugin dam_plugin"
mysql -uroot -S $sockets -e"select version()" | egrep "5.6.16.12-20161009-log|5.6.16.12.3-20161017"
if [ "$?" -ne 0 ]; then
echo $sockets, "ignore"
continue
fi
mysql -uroot -S $sockets -e"set global log_sql_info=ON"
done
service dbfree-dam restart
sleep 10
source /home/mysql/.bash_profile
for sockets in `ps -ef|grep mysqld|awk -F "--socket=" '{print $2}'|awk '{print $1}'`;
do
mysql -uroot -S $sockets -e"select version()" | egrep "5.6.16.12-20161009-log|5.6.16.12.3-20161017"
if [ "$?" -ne 0 ]; then
echo $sockets, "ignore 2"
continue
fi
mysql -uroot -S $sockets -e"set global log_sql_info=ON"
done
echo 'Success'
if not now when,if not me who