有哪些常见的核心的MySQL应用开发规范?

目录

  • 生产环境Redis中的热点key如何发现并优化?
  • 有哪些常见的核心的MySQL应用开发规范?
  • 高可用架构MHA有什么样的不足和风险点吗?
  • 为何pt-osc操做表之后中文注释显示???,如何避免?
  • MySQL 5.6升级5.7都有什么注意事项
  • 在用阿里云、腾讯云等公有云时,你是如何评估新建主机/数据库对象的配置级别?
  • ALTER TABLE 出现duplicate primary xxx报错的缘由及处理?
  • InnoDB在什么状况下会触发检查点(checkpoint)?
  • update t set a=29 and b in (1,2,3,4);这样写有什么问题吗?

1、生产环境Redis中的热点key如何发现并优化?
一、用户消费的数据远大于生产的数据(热卖商品、热点新闻、热点评论、明星直播)
二、请求分片集中,超过单Server的性能极限。html

热点key可能形成以下问题:
一、流量集中,达到物理网卡上限
二、请求过多,缓存分片服务被打垮
三、DB击穿,引发业务雪崩mysql

如何发现热点key:
一、经过tcpdump抓包,能够分析抓取到网络包分析key的频率
二、redis客户端抓取,例如请求key的时候记录日志,分析日志获得key的访问频率
三、redis的monitor能够记录redis的全部操做,记录并分析monitor日志获得key的访问频率(注意:monitor可能会形成性能问题,慎重使用)
四、Redis 4.0提供了—hot-keys配合maxmemory-policy能够统计热点key
五、第三方开源项目,如facebook开源项目redis-faina,原理同3git

解决方案以下:
一、对于”get”类型的热点key,一般能够为redis添加slave,经过slave承担读压力来缓解
二、服务端本地缓存,服务端先请求本地缓存,缓解redis压力
三、多级缓存方案,经过多级请求,层层过滤解决热点key问题
四、proxy方案,有些方案会探测分片热点key,缓存在proxy上缓解redis压力
五、同解决big方案相似,将一个key经过hash分解为多个key,value值同样,将这些key分散到集群多个分片中,须要访问时先根据hash算出对应的key,而后访问的具体的分片github

2、有哪些常见的核心的MySQL应用开发规范?
这里重点介绍下Schema设计规范,其余规范请参考末尾《知数堂开发规范》redis

(一)schema设计原则:
一、尽可能小的原则,不浪费
二、为了高并发,禁止使用外键
三、每一个表必须有主键
四、字符集和库级保持一致,不单独定义字段字符集sql

(二)字段规范:
一、每一个表建议不超过30-50个字段
二、优先选择utf8mb4字符集,它的兼容性最好,并且还支持emoji字符。若是对存储容量比较敏感的,能够改为latin1字符集
三、严禁在数据库中明文存储用户密码、身份证、信用卡号(信用卡PIN码)等核心机密数据,务必先行加密
四、存储整型数据时,默认加上UNSIGNED,扩大存储范围
五、建议用INT UNSIGNED存储IPV4地址,查询时再利用INET_ATON()、INET_NTOA()函数转换
六、若是遇到BLOB、TEXT字段,则尽可能拆出去,再用主键作关联
七、在够用的前提下,选择尽量小的字段,用于节省磁盘和内存空间
八、涉及精确金额相关用途时,建议扩大N倍后,所有转成整型存储(例如把分扩大百倍),避免浮点数加减出现不许确问题数据库

(三)经常使用数据类型参考:
一、字符类型建议采用varchar数据类型(InnoDB建议用varchar替代char)
二、金额货币科学计数建议采用decimal数据类型,若是运算在数据库中完成能够考虑使用bigint存储,单位:分
三、自增加标识建议采用int或bigint数据类型,若是该表有大量的删除及再写入就使用bigint,反之int就够用
四、时间类型建议采用为datetime/timestamp数据类型
五、禁止使用text、longtext等的数据类型
六、字段值若是为非负数,就加上unsigned定语,提高可用范围缓存

(四)SQL规范
一、在MySQL中SQL语句通常不区分大小写,所有小写
二、sql语句在使用join, 子查询必定先要进行explain肯定执行计划
三、为每一个业务收集sql list.安全

知数堂开发规范:https://github.com/zhishutech...服务器

3、高可用架构MHA有什么样的不足和风险点吗?
MHA做为传统复制下的高可用霸主,在今天的GTID环境下,开始慢慢走向没落,更多的人开始开始选择replication-manager或者orchestrator等高可用解决方案

不足及风险点:
一、failover依赖于外部脚本,好比VIP切换须要本身编写脚本实现
二、MHA启动后只检测主库是否正常,并不检查从库状态及主从延迟
三、须要基于SSH免认证配置,存在必定的安全隐患
四、没有提供从服务器的读负载均衡功能
五、从节点出现宕机等异常并无能力处理,即没有从库故障转移能力
六、在高可用切换期间,某些场景下可能出现数据丢失的状况,并不保证数据0丢失
七、没法控制RTO恢复时间

具体的数据丢失场景移步吴老师公开课《把MHA拉下神坛》
https://ke.qq.com/course/430673?tuin=2ce85033

4、为何pt-osc操做表之后中文注释显示???,如何避免?

通常来讲,生产环境使用的表都会使用中文注释表信息以及字段信息,可是若是使用pt-osc且未指定字符类型的状况下进行在线变动后,中文注释都会变成"???",虽然不影响正常使用,可是对于认为阅读起来会形成困扰,某些平台会依据注释生成数据字典,所以正确的姿式是在使用pt-osc工具时经过--charset=utf8指定utf8字符集

示例:

pt-online-schema-change -h 127.0.0.1 -u xxx -p xxx --alter="add index idx_id(id)" --chunk-size=5000 \

--print --no-version-check --execute D=xucl,t=test --charset=utf8

5、MySQL 5.6升级5.7都有什么注意事项

(一)MySQL升级的方式通常来讲有两种
一、经过inplace方式原地升级,升级系统表
二、经过新建实例,高版本做为低版本的从库进行滚动升级

MySQL5.7版本作了很是多的改变,升级5.6到5.7时须要考虑兼容性,避免升级到5.7以后由于种种参数设置不正确致使业务受影响,建议首先逐一查看release note

(二)须要注意的参数及问题:
一、sql_mode:MySQL 5.7采用严格模式,例如ONLY_FULL_GROUP_BY等

二、innodb_status_output_locks:MySQL 5.7支持将死锁信息打印到error log(其实这个参数MySQL 5.6就已支持)

三、innodb_page_cleaners:MySQL 5.7将脏页刷新线程从master线程独立出来了,对应参数为innodb_page_cleaners

四、innodb_strict_mode:控制CREATE TABLE, ALTER TABLE, CREATE INDEX, 和 OPTIMIZE TABLE的语法问题

五、show_compatibility_56=ON:控制show变量及状态信息输出,若是未开启show status 命令没法获取Slave_xxx 的状态

六、log_timestamps:控制error log/slow_log/genera log日志的显示时间,该参数能够设置为:UTC 和 SYSTEM,可是默认使用 UTC

七、disable_partition_engine_check:在表多的状况下可能致使启动很是慢

八、range_optimizer_max_mem_size:范围查询优化参数,这个参数限制范围查询优化使用的内存,默认8M

九、MySQL 5.7新增优化器选项derived_merge=on,可能致使SQL全表扫描,而在MySQL 5.6下可能表现为auto key

十、innodb_undo_directory && innodb_undo_logs:MySQL 5.7支持将undo从ibdata1独立出来(只支持实例初始化,不支持在线变动)

十一、主从复制问题:MySQL5.7到小于5.6.22的复制存在bug(bug 74683)

十二、SQL兼容性问题:SQL在MySQL 5.7和MySQL 5.6环境下结果可能不一致,所以建议获取线上SQL,在一样数据的环境下,在两个实例运行获取到的结果计算hash,比较hash值作兼容性判断

(三)友情提醒
一、升级前必定要作好备份!!!
二、升级正式环境前提早在测试环境进行仔细测试,确认无误之后再升级正式环境
三、作好相应的回退方案

6、在用阿里云、腾讯云等公有云时,你是如何评估新建主机/数据库对象的配置级别?

这里以云下业务迁移云上为例来探讨

一、首先熟悉现有业务的基本架构,好比一主多从、sharding架构等,而且知道相应的业务分布

二、获取现有业务的监控获取到的峰值QPS、TPS、IOPS、CPU使用率、磁盘使用量、内存使用量、最大链接数等关键指标

三、获取现有数据库的关键参数指标,如innodb_buffer_pool_size等

四、公有云每一个规格都提供了相应的参数指标,如:核数、内存、IOPS、最大链接数等指标

五、根据第二、三、4步选择相应规格的RDS,原则为RDS规格参数大于现有环境状态指标,其中IOPS须要进行换算(云上的IOPS通常按4k算,而自建的通常按16k算)

六、上云前最好先购买实例进行测试,包括使用sysbench进行标准压测、业务兼容性测试、业务压测等来判断实例规格是否知足性能要求,,建议云上实例性能预留好比20-30%浮动空间

七、特别提醒,云上实例一般会把binlog以及SQL运行产生的临时表、临时文件也计入磁盘空间,此外云上数据表的碎片率可能会比自建实例大不少(曾经遇到本地5G的表云上占用120G),所以要特别注意磁盘空间要预留充足

八、最后说明一点,迁移云上最好选择数据库版本同自建版本。还有,尽可能不要使用云上数据

7、ALTER TABLE 出现duplicate primary xxx报错的缘由及处理?

好多同窗都曾经问过这个问题,还有同窗说这是bug,实际上这并非bug

(一)缘由分析
一、Online DDL操做时MySQL会将DML操做缓存起来存入到变动日志
二、等到DDL执行完成后再应用变动日志中的DML操做
三、在Oline DDL执行期间,并行的DML可能会没先检查惟一性直接插入一条相同主键的数据,这时并不会致使DDL报错,而是在DDL执行完成再次应用变动日志时才报错,最终致使DDL报错执行失败

(二)问题说明
其实这是Online DDL的正常状况,官方文档说明以下:

When running an in-place online DDL operation, the thread that runs the ALTER TABLE statement applies an online log of DML operations that were run concurrently on the same table from other connection threads. When the DML operations are applied, it is possible to encounter a duplicate key entry error (ERROR 1062 (23000): Duplicate entry), even if the duplicate entry is only temporary and would be reverted by a later entry in the online log. This is similar to the idea of a foreign key constraint check in InnoDB in which constraints must hold during a transaction

ref:https://dev.mysql.com/doc/ref...

(三)建议
一、推荐使用pt-osc、gh-ost等第三方工具进行DDL操做
二、建议在业务低谷期进行操做

8、InnoDB在什么状况下会触发检查点(checkpoint)?

(一)MySQL的checkpoint分类
一、sharp checkpoint(激烈检查点,要求尽快将全部脏页都刷到磁盘上,对I/O资源的占有优先级高)
二、fuzzy checkpoint(模糊检查点,会根据系统负载及脏页数量适当平衡,不要求当即将全部脏页写入磁盘,这事默认的方式)

(二)触发时机
一、数据库正常关闭时,即innodb_fast_shutdown=0时须要执行sharp checkpoint

二、redo log发生切换时或者redo log快满的时候进行fuzzy checkpoint

三、master thread每隔1秒或10秒按期进行fuzzy checkpoint

四、innodb保证有足够多的空闲page,若是发现不足,须要移除lru list末尾的page,若是这些page是脏页,那么也须要fuzzy checkpoint

五、innodb buffer pool中脏页比超过innodb_max_dirty_pages_pct时也会触发fuzzy checkpoint

(三)checkpoint相关参数及状态
一、innodb_fast_shutdown

二、innodb_io_capacity/innodb_io_capacity_max

三、innodb_lru_scan_depth

四、innodb_max_dirty_pages_pct/innodb_max_dirty_pages_pct_lwm

五、Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total

六、Innodb_buffer_pool_wait_free

9、update t set a=29 and b in (1,2,3,4);这样写有什么问题吗?

(一)SQL分析
乍一看这个SQL貌似没有什么问题,本意是将t表中b的值属于1/2/3/4的数据的a列修改成29,但实际上该SQL是将t表数据的a列改为了条件29 & b in (1,2,3,4)的真假判断值

即:update t set a = (29 and b in (1,2,3,4));

修改后的SQL应该为update t set a = 29 where b in (1,2,3,4);

(二)注意事项

一、生产环境中进行批量数据修改时应该开启事务,修改确认后再进行提交操做
二、进行DML操做时,建议仍是经过SQL审核工具审核后执行
三、建议打开sql_safe_updates选项,避免没有WHERE条件的更新、删除操做


有任何问题均可以加微信讨论,欢迎沟通~~ 互相进步!

微信:lvqingshan_

公众号:知数堂,更多MySQL干货知识,关注公众号获取。

原文连接:https://zhishutang.com/T5U

相关文章
相关标签/搜索