关于dba:DBA的40条军规

6次阅读

共计 5107 个字符,预计需要花费 13 分钟才能阅读完成。

1、波及业务上的批改 / 删除数据,在失去业务方、CTO 的邮件批准前方可执行,执行前提前做好备份,必要时可逆。


2、所有上线需要必须走工单零碎,口头告诉视为有效。


3、在对大表做表构造变更时,如批改字段属性会造成锁表,并会造成从库提早,从而影响线上业务,必须在凌晨 0:00 后业务低峰期执行,另对立用工具 pt-online-schema-change 防止锁表且升高提早执行工夫。

应用范例:

#pt-online-schema-change –alter=”add index IX_id_no(id_no)”

–no-check-replication-filters –recursion-method=none –user=dba

–password=123456 D=test,t=t1 –execute

对于 MongoDB 创立索引要在后盾创立,防止锁表。

应用范例:

db.t1.createIndex({idCardNum:1},{background:1})


4、所有线上业务库均必须搭建 MHA 高可用架构,防止单点问题。


5、给业务方开权限时,明码要用 MD5 加密,至多 16 位。权限如没有特殊要求,均为 select 查问权限,并做库表级限度。


6、删除默认空明码账号。

delete from mysql.user where user=” and password=”;

flush privileges;


7、汇总库开启 Audit 审计日志性能,呈现问题时方可追溯。


行为规范

8、禁止一个 MySQL 实例寄存多个业务数据库,会造成业务耦合性过高,一旦呈现问题会殃及池鱼,减少了定位故障问题的难度。通常采纳多实例解决,一个实例一个业务库,互不烦扰。


9、禁止在主库上执行后盾治理和统计类的性能查问,这种简单类的 SQL 会造成 CPU 的升高,进而会影响业务。


10、批量荡涤数据,须要开发和 DBA 独特进行审查,应避开业务高峰期时段执行,并在执行过程中察看服务状态。


11、促销流动等应提前与 DBA 当面沟通,进行流量评估,比方提前一周减少机器内存或扩大架构,避免 DB 呈现性能瓶颈。


12、禁止在线上做数据库压力测试。


根本标准

13、禁止在数据库中存储明文明码。


14、应用 InnoDB 存储引擎。

  • 反对事务,行级锁,更好的恢复性,高并发下性能更好。
  • InnoDB 表防止应用 COUNT(*) 操作,因外部没有计数器,须要一行一行累加计算,计数统计实时要求较强能够应用 memcache 或者 Redis。
    • *

15、表字符集对立应用 UTF8。

  • 不会产生乱码危险。
    • *

16、所有表和字段都须要增加中文正文。

  • 不便别人、不便本人。
    • *

17、不在数据库中存储图片、文件等大数据。

  • 图片、文件更适宜于 GFS 分布式文件系统,数据库里寄存超链接即可。
    • *

18、防止应用存储过程、视图、触发器、事件。

MySQL 是 OLTP 利用,最善于简略的增、删、改、查操作,但对逻辑计算剖析类的利用,并不适宜,所以这部分的需要最好通过程序上实现。


19、防止应用外键,外键用来爱护参照完整性,可在业务端实现。

  • 外键会导致父表和子表之间耦合,非常影响 SQL 性能,呈现过多的锁期待,甚至会造成死锁。
    • *

20、对事务一致性要求不高的业务,如日志表等,优先选择存入 MongoDB。

  • 其本身反对的 sharding 分片性能,加强了横向扩大的能力,开发不必过多调整业务代码。
    • *

库表设计规范

21、表必须有主键,例如自增主键。

  • 这样能够保证数据行是依照程序写入,对于 SAS 传统机械式硬盘写入性能更好,依据主键做关联查问的性能也会更好,并且还不便了数据仓库抽取数据。从性能的角度来说,应用 UUID 作为主键是个最不好的办法,它会使插入变得随机。
    • *

22、禁止应用分区表。

  • 分区表的益处是对于开发来说,不必批改代码,通过后端 DB 的设置,比方对于工夫字段做拆分,就能够轻松实现表的拆分。但这外面波及一个问题,查问的字段必须是分区键,否则会遍历所有的分区表,并不会带来性能上的晋升。此外,分区表在物理构造上仍旧是一张表,此时咱们更改表构造,一样不会带来性能上的晋升。所以应采纳切表的模式做拆分,如程序上须要对历史数据做查问,可通过 union all 的形式关联查问。另外随着工夫的推移,历史数据表不再须要,只需在从库上 dump 进去,即便捷地迁徙至备份机上。

字段设计规范

23、用 DECIMAL 代替 FLOAT 和 DOUBLE 存储准确浮点数。
浮点数的毛病是会引起精度问题,请看上面一个例子:

mysql> CREATE TABLE t3 (c1 float(10,2),c2 decimal(10,2));

Query OK, 0 rows affected (0.05 sec)

mysql> insert into t3 values (999998.02, 999998.02);

Query OK, 1 row affected (0.01 sec)

mysql> select * from t3;

| c1 | c2 |

| 999998.00 | 999998.02 |

1 row in set (0.00 sec)

能够看到 c1 列的值由 999998.02 变成了 999998.00,这就是 float 浮点数类型的不精确性造成的。因而对货币等对精度敏感的数据,应该用定点数示意或存储。


24、应用 TINYINT 来代替 ENUM 类型。

采纳 enum 枚举类型,会存在扩大的问题,例如用户在线状态,如果此时减少了:5 示意请勿打扰、6 示意散会中、7 示意隐身对好友可见,那么减少新的 ENUM 值要做 DDL 批改表构造操作了。


25、字段长度尽量按理论须要进行调配,不要随便调配一个很大的容量。

抉择字段的个别准则是保小不保大,能用占用字节少的字段就不必大字段。比方主键,强烈建议用 int 整型,不必 uuid,为什么?省空间啊。空间是什么?空间就是效率!按 4 个字节和按 32 个字节定位一条记录,谁快谁慢太显著了。波及几个表做 join 时,成果就更显著了。更小的字段类型域名交易占用的内存就更少,占用的磁盘空间和磁盘 I / O 也会更少,而且还会占用更少的带宽。

有不少开发人员在设计表字段时,只有是针对数值类型的全副用 int,但这不肯定适合,就比方用户的年龄,一般来说,年龄大都在 1~100 岁之间,长度只有 3,那么用 int 就不适宜了,能够用 tinyint 代替。又比方用户在线状态,0 示意离线、1 示意在线、2 示意来到、3 示意繁忙、4 示意隐身等,其实相似这样的状况,用 int 都是没有必要的,节约空间,采纳 tinyint 齐全能够满足需要,int 占用的是 4 字节,而 tinyint 才占用 1 个字节。

int 整型有符号(signed)最大值是 2147483647,而无符号(unsigned)最大值是 4294967295,如果你的需要没有存储正数,那么倡议改成有符号(unsigned),能够减少 int 存储范畴。

int(10) 和 int(1) 没有什么区别,10 和 1 仅是宽度而已,在设置了 zerofill 扩大属性的时候有用,例:

root@localhost(test)10:39>create table test(id int(10) zerofill,id2 int(1));

Query OK, 0 rows affected (0.13 sec)

root@localhost(test)10:39>insert into test values(1,1);

Query OK, 1 row affected (0.04 sec)

root@localhost(test)10:56>insert into test values(1000000000,1000000000);

Query OK, 1 row affected (0.05 sec)

root@localhost(test)10:56>select * from test;

| id | id2 |

| 0000000001 | 1 |

| 1000000000 | 1000000000 |

2 rows in set (0.01 sec)


26、字段定义为 NOT NULL 要提供默认值。
从应用层角度来看,能够缩小程序判断代码,比方你要查问一条记录,如果没默认值,你是不是得先判断该字段对应变量是否被设置,如果没有,你得通过 java 把该变量置为 ” 或者 0,如果设了默认值,判断条件可间接略过。

NULL 值很难进行查问优化,它会使索引统计更加简单,还须要 MySQL 外部进行非凡解决。


27、尽可能不应用 TEXT、BLOB 类型。

  • 减少存储空间的占用,读取速度慢。

索引标准

28、索引不是越多越好,按理论须要进行创立。

  • 索引是一把双刃剑,它能够进步查问效率但也会升高插入和更新的速度并占用磁盘空间。适当的索引对利用的性能至关重要,而且在 MySQL 中应用索引它的速度是极快的。遗憾的是,索引也有相干的开销。每次向表中写入时(如 INSERT、UPDATEH 或 DELETE),如果带有一个或多个索引,那么 MySQL 也要更新各个索引,这样索引就减少了对各个表的写入操作的开销。只有当某列被用于 WHERE 子句时,能力享受到索引的性能晋升的益处。如果不应用索引,它就没有价值,而且会带来保护上的开销。
    • *

29、查问的字段必须创立索引。

  • 如:1、SELECT、UPDATE、DELETE 语句的 WHERE 条件列;2、多表 JOIN 的字段。
    • *

30、不在索引列进行数学运算和函数运算。
无奈应用索引,导致全表扫描。
例:SELECT * FROM t WHERE YEAR(d) >= 2016;
因为 MySQL 不像 Oracle 那样反对函数索引,即便 d 字段有索引,也会间接全表扫描。
应改为 —–>
SELECT * FROM t WHERE d >= ‘2016-01-01’;


31、不在低基数列上建设索引,例如‘性别’。
有时候,进行全表浏览要比必须读取索引和数据表更快,尤其是当索引蕴含的是均匀散布的数据集是更是如此。对此典型的例子是性别,它有两个均匀分布的值(男和女)。通过性别须要读取大略一半的行。在种状况下进行全表扫描浏览要更快。


32、不应用 % 前导的查问,如 like‘%xxx’。
无奈应用索引,导致全表扫描。

低效查问

SELECT * FROM t WHERE name LIKE ‘%de%’;

—–>

高效查问

SELECT * FROM t WHERE name LIKE ‘de%’;


33、不应用反向查问,如 not in / not like。
无奈应用索引,导致全表扫描。


34、防止冗余或反复索引。
联结索引 IX_a_b_c(a,b,c) 相当于 (a)、(a,b)、(a,b,c),那么索引 (a)、(a,b) 就是多余的。


SQL 设计规范

35、不应用 SELECT,只获取必要的字段。*
耗费 CPU 和 IO、耗费网络带宽;
无奈应用笼罩索引。


36、用 IN 来替换 OR。

低效查问

SELECT * FROM t WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30;

—–>

高效查问

SELECT * FROM t WHERE LOC_IN IN (10,20,30);


37、防止数据类型不统一。

SELECT * FROM t WHERE id = ’19’;

—–>

SELECT * FROM t WHERE id = 19;


38、缩小与数据库的交互次数。

INSERT INTO t (id, name) VALUES(1,’Bea’);

INSERT INTO t (id, name) VALUES(2,’Belle’);

INSERT INTO t (id, name) VALUES(3,’Bernice’);

—–>

INSERT INTO t (id, name) VALUES(1,’Bea’), (2,’Belle’),(3,’Bernice’);

Updatewhere id in (1,2,3,4);

Alter table tbl_name add column col1, add column col2;


39、回绝大 SQL,拆分成小 SQL。

低效查问

SELECT * FROM tag

JOIN tag_post ON tag_post.tag_id = tag.id

JOIN post ON tag_post.post_id = post.id

WHERE tag.tag = ‘mysql’;

能够分解成上面这些查问来代替

—–>

高效查问

SELECT * FROM tag WHERE tag = ‘mysql’

SELECT * FROM tag_post WHERE tag_id = 1234

SELECT * FROM post WHERE post_id in (123, 456, 567, 9098, 8904);


40、禁止应用 order by rand()

SELECT * FROM t1 WHERE 1=1 ORDER BY RAND() LIMIT 4;

—->

SELECT FROM t1 WHERE id >= CEIL(RAND()1000) LIMIT 4;

正文完
 0