- 表达你要的, 而不是不要的
- 表达感受, 而不是情绪
表达自己是愤怒的, 而不是愤怒的表达 - 表达你的需求而不是抱怨
不要让对方猜测, 我想要什么. - 表达你要区的方向, 而不是抱怨所在的位置
看目标, 而不是陷在事件里
tcp-faq
TCP 是传输层协议, 对应 OSI 网络模型的第四层传输层, 特点如下.
TCP 协议是基于链接的, 也就是传输数据前需要先建立好链接, 然后再进行传输.
TCP 链接一旦建立, 就可以在链接上进行双向的通信.
TCP 的传输是基于字节流而不是报文, 将数据按字节大小进行编号, 接收端通过 ACK 来确认收到的数据编号, 通过这种机制, TCP 协议能够保证接收数据的有序性和完整性, 因此 TCP 能够提供可靠性传输.
TCP 还能提供流量控制能力, 通过滑动窗口来控制数据的发送速率. 滑动窗口的本质是动态缓冲区, 接收端根据自己的处理能力, 在 TCP 的 Header 中动态调整窗口大小, 通过 ACK 应答包通知给发送端, 发送端根据窗口大小调整发送的的速度.
仅仅有了流量控制能力还不够, TCP 协议还考虑到了网络问题可能会导致大量重传, 进而导致网络情况进一步恶化, 因此 TCP 协议还提供拥塞控制. TCP 处理拥塞控制主要用到了慢启动, 拥塞避免, 拥塞发生, 快速恢复四个算法, 感兴趣的同学可以进一步了解.
1. TCP 协议问题, 例如特定场景下 Nagel 和 ACK 延迟机制配合使用可能会出现 delay40ms 超时后才回复 ACK 包的问题.
2. 3 次握手
3. 4 次挥手
4. SYN 洪水攻击
SYN 洪水攻击发生的原因, 就是 Server 端收到 Client 端的 SYN 请求后, 发送了 ACK 和 SYN, 但是 Client 端不进行回复, 导致 Server 端大量的链接处在 SYN_RCVD 状态, 进而影响其他正常请求的建连. 可以设置 tcp_synack_retries = 0 加快半链接的回收速度, 或者调大 tcp_max_syn_backlog 来应对少量的 SYN 洪水攻击
performance
性能问题分析:
- 预
服务硬件配置达不到要求
服务配置不正确
软件开发设计不正确
软件开发没有遵守规范
- 前 I/O 问题
发起连接
- 中 CPU 问题
请求处理
- 后 I/O 问题
结果传输
column
用于字段对齐
不太好的地方就是必须等前面的命令执行完成后才输出
1 | vmstat 1 5 | column -t |
vmstat
mysql-cmd-dml
DML, Data Manipulation Language, 数据操作语言
用于对数据的操作
- Insert
- Delete
- Update
- Select
1. 算时间差
1 | select timestampdiff(second, now(), '2011-01-27 15:52:11'); |
2. 横向排列
1 | select |
3. join
假如 A 表 join B 表
- inner join
A B 交集
1 | select * from a |
- full outer join
A B 并集
1 | select * from a |
- left outer join
产生表 A 的完全集, 而 B 表中匹配的则有值, 没匹配的以 null 值取代.
1 | select * from a |
- left outer join on where
产生在 A 表中有而在 B 表中没有的集合.
1 | select * from a |
- right outer join
产生表 B 的完全集, 而 A 表中匹配的则有值, 没匹配的以null值取代.
1 | select * from a |
- right outer join on where
产生在 B 表中有而在 A 表中没有的集合.
1 | select * from a |
- full outer join on where
产生 ( A 表中有但 B 表没有) 和 ( B 表中有但 A 表中没有) 的数据集.
1 | select * from a |
- cross join
交差集, A * B, 性能较差, 不建议使用
mysql-cmd-ddl
DDL, Data Definition Language, 数据定义语言
用于对数据库中的表, 视图的操作
- Create
- Drop
- Alter
1. 查看表结构
1 | show columns from $table_name; |
2. 查看表大小
1 | show table status like '$table_name'; |
3. 添加库
1 | create database if not exists $database_name default charset utf8 collate utf8_general_ci; |
4. 删除列
1 | alter table $table_name drop $column_name; |
5. 增加列
1 | alter table $table_name add $column_name int not null comment $comment; |
6. 增加列
1 | alter table $table_name add $column_name int not null comment $comment; |
7. 修改列的类型信息
1 | alter table $table_name change $column_name $new_column_name bigint not null comment $comment; |
8. 重命名表
1 | alter table $table_name rename $new_table_name; |
9. 删除表中主键
1 | alter table $table_name drop primary key; |
10. 添加主键
1 | alter table $table_name add constraint $pk_name primary key (resid, resfromid); |
11. 添加索引
1 | alter table $table_name add index $idx_name ($column_name); |
12. 添加唯一限制条件索引
1 | alter table $table_name add unique $uk_name($column_name); |
13. 删除索引
1 | alter table $table_name drop index $idx_name; |
14. 修改 auto_increment
1 | alter table $table_name auto_increment=1; |
15. 改变字段顺序
1 | alter table student modify id int(10) unsigned auto_increment first; |
16. 创建表
1 | create table if not exists user ( |
17. 修改字符集
1 | show table status from @database like '@table'; |
18. 查看有哪些自定义的函数
1 | select SPECIFIC_NAME from ROUTINES where ROUTINE_TYPE = 'FUNCTION' and DEFINER = 'root@%' ; |
mysql-partition
1. MySQL支持的分区类型有哪些?
-
RANGE分区: 这种模式允许将数据划分不同范围. 例如可以将一个表通过年份划分成若干个分区
-
LIST分区: 这种模式允许系统通过预定义的列表的值来对数据进行分割. 按照List中的值分区, 与RANGE的区别是, range分区的区间范围值是连续的.
-
HASH分区 : 这中模式允许通过对表的一个或多个列的Hash Key进行计算, 最后通过这个Hash码不同数值对应的数据区域进行分区. 例如可以建立一个对表主键进行分区的表.
-
KEY分区 : 上面Hash模式的一种延伸, 这里的Hash Key是MySQL系统产生的.
2. 表分区有什么好处?
-
存储更多数据. 分区表的数据可以分布在不同的物理设备上, 从而高效地利用多个硬件设备. 和单个磁盘或者文件系统相比, 可以存储更多数据
-
优化查询. 在where语句中包含分区条件时, 可以只扫描一个或多个分区表来提高查询效率; 涉及sum和count语句时, 也可以在多个分区上并行处理, 最后汇总结果.
-
分区表更容易维护. 例如: 想批量删除大量数据可以清除整个分区.
-
避免某些特殊的瓶颈, 例如InnoDB的单个索引的互斥访问.
3. 分区表的限制因素
-
一个表最多只能有1024个分区
-
MySQL5.1中, 分区表达式必须是整数, 或者返回整数的表达式. 在MySQL5.5中提供了非整数表达式分区的支持.
-
如果分区字段中有主键或者唯一索引的列, 那么多有主键列和唯一索引列都必须包含进来. 即: 分区字段要么不包含主键或者索引列, 要么包含全部主键和索引列.
-
分区表中无法使用外键约束
-
MySQL的分区适用于一个表的所有数据和索引, 不能只对表数据分区而不对索引分区, 也不能只对索引分区而不对表分区, 也不能只对表的一部分数据分区.
mysql-cmd-dcl
DCL, Data Control Language, 数据控制语言
用于控制数据权限
- Grant
- Revoke
1. 创建新用户
1 | create user root@'%' identified WITH mysql_native_password BY 'password'; |
2. 修改用户
1 | ALTER USER 'root'@'localhost' IDENTIFIED BY 'root' PASSWORD EXPIRE NEVER; #修改加密规则 |
或者使用 mysqladmin:
1 | /usr/bin/mysqladmin -u root password new-password |
3. 查看支持的引擎
1 | show engine; |
4. 查看 MySQL 参数
1 | -- 是否支持分区 |
5. 查看连接列表
1 | show processlist; |
1 | mysql -e 'show processlist\G' | grep 'State:' | sort | uniq -c | sort -rn |
6. explain
1 | explain @sql; |
7. 查看表状态
1 | -- 查看表状态 |
8. 查看实时 sql 记录
1 | -- 日志开启 |
9. 查看慢查询
1 | -- 查看慢查询是否开始, 存储文件位置 |
10. 分析 SQL 执行时间
1 | show variables like 'PROFILING'; |
11. 表结构优化建议
1 | -- 会给出每一列的优化建议. |
12. 定期回收闲置的数据库空间
1 | optimize table table_name; |
13. 导入文件
1 | source /file/to/source.sql |
1 | mysql < /file/to/source.sql |
14. 导出
1 | # 导出查询结果 |
15. 查看 bin log
1 | -- 查看 bin log 状态 |
1 | mysqlbinlog mysql-bin.000004 | tail; |
16. Resource
B-Tree
1. B-Tree
平衡多路查找树
一棵 m 阶的 B-Tree, 或为空树, 或为满足以下特性的 m 叉树:
- 树中的每个结点至多有 m 棵子树
- 若根结点不是叶子结点, 则至少有 2 棵子树
- 除根结点外的所有分支结点至少有 ⌈m/2⌉ 棵子树
⌈m/2⌉ 即不超过 m/2 的整数 - 所有的非叶子结点中包含下列信息数据: (n,P0,K1,P1,K2,P2,...,Kn,Pn)
n 为关键字数量, ⌈m/2⌉≤n≤m−1, n+1 为子树个数
Ki(i=1…n) 为关键字, 且关键字按从小到大顺序排列
Pj−1(j=0…n) 为指向指向子树的指针, 且关键字 K 左指针指向的子树中的所有关键字都比 K 小, 关键字 K 右指针指向的子树中的所有关键字都比 K 大 - 所有叶子结点都出现在同一层次, 并且不带信息(可以看作是外部结点或查找失败的结点, 实际上这些结点不存在, 指向这些结点的指针为空)
2. B+Tree
B+Tree 是应文件系统所需而出的 B-Tree 的变型树.
一棵 m 阶的 B-Tree 和一棵 m 阶的 B+Tree 差异在于:
- 有 n 棵子树的结点中含有 n 个关键字
关键字个数与指针个数相同 - 所有的非叶子结点可以看成是索引部分, 结点中仅含有其子树中的最大(或最小)关键字
- 所有的叶子结点中包含了全部的关键字信息, 及指向含这些关键字记录的指针, 且叶子结点本身按关键字的大小从小到大链接
非叶子不包含数据, 只是索引, 只有叶子结点才包含数据.
通常 B+Tree 上有两个头指针, 一个指向根结点, 另一个指向关键字最小的叶子结点.
因此可以堆 B+Tree 进行两种遍历运算:
- 从根结点开始进行随机查找
- 从最小关键字开始顺序查找
B+Tree 查找时, 如果非叶子结点上的关键字等于给定的值, 并不终止, 而是继续修改下直到叶子结点.
3. B*Tree
B树是B+树的变体, 在B+树的非根和非叶子结点再增加指向兄弟的指针; B树定义了非叶子结点关键字个数至少为(2/3)*M, 即块的最低使用率为2/3 (代替B+树的1/2) .
B+树的分裂: 当一个结点满时, 分配一个新的结点, 并将原结点中1/2的数据复制到新结点, 最后在父结点中增加新结点的指针; B+树的分裂只影响原结点和父结点, 而不会影响兄弟结点, 所以它不需要指向兄弟的指针;
B*树的分裂: 当一个结点满时, 如果它的下一个兄弟结点未满, 那么将一部分数据移到兄弟结点中, 再在原结点插入关键字, 最后修改父结点中兄弟结点的关键字 (因为兄弟结点的关键字范围改变了) ; 如果兄弟也满了, 则在原结点与兄弟结点之间增加新结点, 并各复制1/3的数据到新结点, 最后在父结点增加新结点的指针;