在 linux 中可以使用free -m命令来查看内存的使用情况(包括 swap 交换分区的使用情况)关于 swap 存在的意义不再讨论, 有的人在某些情况下需要开启 swap 功能以保证程序不会崩溃; 有的人在某些情况下需要关闭 swap 功能以保证”宁宕毋慢”.

开启/关闭 swap 功能

开启

  • swap 文件: swapon /opt/swapfile
  • swap 分区: swapon /dev/sdb1

关闭

  • swap 文件: swapoff /opt/swapfile
  • swap 分区: swapoff /dev/sdb1

如果是系统在安装时设置了 swap, 在后期想要关闭 swap 功能,可以去修改/etc/fstab文件

将包含有 swap 信息的这一行注释掉/dev/mapper/centos-swap swap swap defaults 0 0

增加 swap 空间

制作 swap 文件

1
2
3
4
5
6
7
8
9
10
11
# 创建一个1G的文件作为交换分区使用
➜ ~ dd if=/dev/zero of=/opt/swapfile bs=1M count=1000

# 格式化成swap分区
➜ ~ mkswap /opt/swapfile

# 打开swap分区
➜ ~ swapon /opt/swapfile

# 在/etc/fstab中增加一条记录如下
/opt/swapfile swap swap defaults 0 0

制作 swap 分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 创建一个 swap 分区
➜ ~ fdisk /dev/sdb
# 新建一个分区
n
p
default
default
...
# 修改分区 id 为swap
t
82
# 写入分区表
w

# 同步内存和分区表信息
➜ ~ partprobe

# 格式化成 swap 分区
➜ ~ mkswap /dev/sdb1

# 打开 swap 分区
➜ ~ swapon /dev/sdb1

# 在/etc/fstab中增加一条记录如下
/opt/swapfile swap swap defaults 0 0

Tips: 如果本机已有2G swap 交换分区,又制作了一个8G 的 swap 分区文件, 那么在执行swapon命令之后, swap 空间将为10G(swap 空间会累加)

在日常运维中,我们常常需要检查远程服务器的某个端口是否可用,是否可以连通. 如果远程服务器是使用了 TCP 协议监听了端口, 我们可以使用 telnet 命令来测试端口的连通性; 如果远程服务器使用的了 UDP 协议监听了端口, 我们可以使用 nc 命令来测试端口的连通性. 下面就对这两个命令做简单的使用介绍

telnet ===> TCP

telnet 命令的常用语法: telnet IP port

1
2
3
4
5
➜  ~ telnet 192.168.10.159 22
Trying 192.168.10.159...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_6.6.1

以上测试即为可以连通,而且显示出了应用的名称SSH

退出 telnet 可是按 Ctrl+] 组合键, 得到 > 命令终端后,再输入 quit 退出终端

1
2
3
4
5
6
7
8
➜  ~ telnet 192.168.10.159 22
Trying 192.168.10.159...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_6.6.1
^]
telnet> quit
Connection closed.

telnet 的其他用法请自行百度一下/谷歌一下😆

nc ===> UDP

udp 协议监听的端口是不能用 telnet 命令来测试的,这里用到了 nc 命令

nc 命令的常用语法: nc -zuv IP port

  • z 将输入输出关闭
  • u 开启 UDP 模式
  • v 得到详细输出
1
2
3
4
5
6
7
8
9
10
➜  ~ nc -zuv 192.168.10.159 4500
found 0 associations
found 1 connections:
1: flags=82<CONNECTED,PREFERRED>
outif (null)
src 10.1.100.12 port 53092
dst 192.168.10.159 port 4500
rank info not available

Connection to 192.168.10.159 port 4500 [udp/ipsec-msft] succeeded!

nc 是一个强大的网络工具, 功能不仅限于此

查看当前路由表

1
2
3
4
5
6
> route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default localhost 0.0.0.0 UG 100 0 0 eno16780032
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.10.0 0.0.0.0 255.255.255.0 U 100 0 0 eno16780032

macOS 中使用 netstat -nr 命令来查看当前路由表

  • Destination 目标网路
  • Gateway 网关
  • Genmask 掩码
  • Flags 标识
    • U 路由已经启动
    • H 路由目标为主机
    • G 使用网关
    • R 为动态路由复原路由表
    • D 由守护进程或间接动态安装
    • M 被路由守护进程或间接修改
    • A 通过addrconf修改
    • C 缓存条目
    • ! 拒绝路由
  • Metric 路由开销, 到目标的‘距离’(通常基于跳数统计)
  • Ref 参考此路由的数量
  • Use 路由查找计数。依赖与使用-F 还是-C选项,这个值要么是路由缓存未命中数要么是命中数
  • Iface 此路由数据包发送到的网络接口

添加路由

添加到主机的路由

route add –host 192.168.59.2 dev eth1

route add –host 192.168.59.2 gw 192.168.10.85

添加到网络的路由

route add -net 192.168.248.0/24 gw 192.168.10.85

route add –net 192.168.248.0 netmask 255.255.255.0 gw 192.168.10.85

route add –net 192.168.248.0 netmask 255.255.255.0 dev eth1

添加默认网关

route add default gw 192.168.10.85

route add -net 0.0.0.0 gw 192.168.10.85

使用route 命令添加的路由,机器重启或者网卡重启后路由就失效了

删除路由

route del –host 192.168.10.85 dev eth1

怎么 add 的就怎么 del 掉. 但是 del 的时候可以不写网关

永久添加路由

  • /etc/rc.local里添加路由信息
1
2
route add -net 192.168.247.0/24 dev eth1
route add -net 192.168.110.0/24 gw 192.168.10.85
  • /etc/sysconfig/network里添加到末尾GATEWAY=gw-ip 或者 GATEWAY=gw-dev
  • /etc/sysconfig/static-router添加any net x.x.x.x/24 gw y.y.y.y

永久添加路由更新 2018-10-12

CentOS7下推荐使用上面第三种方法添加永久静态路由

1
2
3
[root@centos7 ~]# vi /etc/sysconfig/network-scripts/route-enp0s3
10.15.150.0/24 via 192.168.150.253 dev enp0s3
10.25.250.0/24 via 192.168.150.253 dev enp0s3

将永久静态路由需要写到 /etc/sysconfig/network-scripts/route-interface 文件中

注意:

ifcfg-enp0s3 文件改名为 ifcfg-eth0 后,route-enp0s3 文件也要改名为 route-eth0


参考文档:

转换步骤

  • 将kvm中要迁移的虚拟机关机
  • 找到该虚拟机对应的.img文件
  • 使用qemu-img convert命令将img文件转换为vmdk文件
  • vmdk文件传送到ESXi主机上
  • vCenter中创建一个配置相同的主机,加载已存在的vmdk硬盘文件
  • 开启虚拟机即可

qemu-img命令的时候用

qemu-img命​令​行​工​具​是​Xen和​KVM用​来​格​式​化​各​种​文​件​系​统​的​,可​使​用​qemu-img格​式​化​虚​拟​客​户​端​映​像​、​附​加​存​储​设​备​以​及​网​络​存​储​。还可以用来转换镜像文件

创建磁盘文件

创​建​新​磁​盘​映​像​文​件​名​为​ sina_kvm,格​式​为​ format

1
qemu-img create [-6] [-e] [-b base_image] [-f format] filename [sina_kvm]

例如:创建一个10M的镜像文件:ps_kvm.img,文件格式为:raw

转换镜像格式

1
qemu-img convert [-c] [-e] [-f format] filename [-O output_format] output_filename

例如:

1
qemu-img convert 10-71-hadoop.shennong.ren.img -O vmdk /tmp/testhdp.vmdk

获取镜像信息

1
qemu-img info [-f format] filename

支持的格式

映​像​格​式​通​常​是​自​动​获​取​的​。​支​持​以​下​格​式​:

  • raw

Raw 磁​盘​映​像​格​式​(默​认​)。​这​个​格​式​的​优​点​是​可​以​简​单​、​容​易​地​导​出​到​其​它​模​拟​器​中​。​如​果​您​的​文​件​系​统​支​持​中​断​(例​如​在​ Linux 中​的​ ext2 或​者​ ext3 以​及​ Windows 中​的​ NTFS),那​么​只​有​写​入​的​字​段​会​占​用​空​间​。​使​用​ qemu-img info 了​解​ Unix/Linux 中​映​像​或​者​ ls -ls 使​用​的​实​际​大​小​。​

  • qcow2

QEMU 映​像​格​式​,最​万​能​的​格​式​。​使​用​它​可​获​得​较​小​映​像​(如​果​您​的​系​统​不​支​持​中​断​,例​如​在​ Windows 中​,它​会​很​有​用​)、​额​外​的​ AES 加​密​法​、​zlib 压​缩​以​及​对​多​ VM 快​照​的​支​持​。​目前也是虚拟池一直在使用的镜像格式。
例如:
转换之前,原镜像disk size大小为8G,转换后仅仅只有2.3G。

  • qcow

旧​的​ QEMU 映​像​格​式​。​只​用​于​与​旧​版​本​兼​容​,目前虚拟池已无该格式镜像文件。​

  • cow

写​入​映​像​格​式​的​用​户​模​式​ Linux 副​本​。​包​含​ cow 格​式​的​目​的​只​是​为​了​与​前​面​的​版​本​兼​容​。​它​无​法​在​ Windows 中​使​用​,虚拟池已无该格式镜像文件。

  • vmdk

VMware 3 和​ 4 兼​容​映​像​格​式,虚拟池无该格式镜像文件​。​

  • cloop

Linux 压​缩​回​送​映​像​,只​有​在​重​复​使​用​直​接​压​缩​的​ CD-ROM 映​像​时​有​用​,比​如​在​ Knoppix CD-ROM 中​。


参考文章

安装软件

1
yum install ppp pptp pptp-setup

创建VPN连接

1
pptpsetup  --create vpnname --server x.x.x.x  --username uaername --password XXXXXX --encrypt --start
  • create是创建的连接名称
  • server是vpn的ip地址
  • username是用户名
  • password是密码,也可以没这个参数,命令稍后会自动询问。这样可以保证账号安全
  • encrypt 是表示需要加密,不必指定加密方式,命令会读取配置文件中的加密方式(默认使用require-mppe-128加密)
  • start是表示创建连接完后马上连接

连接已有的VPN配置

1
pon vpnname

这个命令在系统中bin目录中找不到,在pptd的安装目录下的script目录下,如果不清楚这个命令具体在哪里的可以执行以下命令查找

1
find / -name "poff" -type f

我使用yum安装的软件,可以参考去以下路径查找

/usr/share/doc/ppp-2.4.5/scripts/

路由

连接成功后会在本地创建一个虚拟网口ppp0

相关的路由也会加在路由表中,可以通过route -nifconfig命令查看

VPN连通后,可以指定本地所有流量都走VPN,也可以指定某几个网段的流量走VPN

  • 所有流量都走VPN,设置为默认路由
1
2
3
route add -net 0.0.0.0 dev ppp0

route add default dev ppp0

删除

1
2
3
route del -net 0.0.0.0 dev ppp0

route del default
  • 指定网段的流量走VPN
1
route add -net 192.168.168.0/24 dev ppp0

注意:重启网卡也会清除VPN通道

关闭VPN通道

1
poff vpnname (全部下线poff -a)

这个命令在系统中bin目录中找不到,在pptd的安装目录下的script目录下,如果不清楚这个命令具体在哪里的可以执行以下命令查找

1
find / -name "poff" -type f

我使用yum安装的软件,可以参考去以下路径查找

/usr/share/doc/ppp-2.4.5/scripts/

相关目录

  • /etc/ppp/peers/ 存放用户创建的vpnname配置文件的地方
  • /etc/ppp/chap-secrets 用户名密码存放的地方(明文的)

  • 注1: pon 和 poff命令可在ppp源码目录下的scripts目录中找到。
  • 注2: 要想使用vpn通道,需要根据需要在本地添加静态路由

查看路由

linux

1
2
3
4
5
> route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.3.1 0.0.0.0 UG 100 0 0 eth0
192.168.3.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0

mac

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
> netstat -nr
Routing tables

Internet:
Destination Gateway Flags Refs Use Netif Expire
default 10.1.101.254 UGSc 214 718 en0
10.1.100/23 link#4 UCS 11 0 en0
10.1.100.22 link#4 UHLWIi 1 1 en0
10.1.100.65/32 link#4 UCS 2 0 en0
10.1.100.65 60:3:8:a5:3b:9e UHLWIi 1 3 lo0
10.1.100.88 link#4 UHLWIi 1 3 en0
10.1.100.94 link#4 UHLWIi 1 2 en0
10.1.100.99 link#4 UHLWIi 1 3 en0
10.1.100.100 link#4 UHLWIi 1 3 en0
10.1.100.121 link#4 UHLWIi 1 3 en0
10.1.100.146 90:b6:86:d8:d:24 UHLWIi 1 1 en0 867
10.1.101.128 link#4 UHLWIi 1 2 en0
10.1.101.164 c8:25:e1:61:70:2e UHLWIi 1 1 en0 1004
10.1.101.254/32 link#4 UCS 2 0 en0
10.1.101.254 b0:aa:77:1a:b0:58 UHLWIir 215 16 en0 782
10.1.101.255 link#4 UHLWbI 1 142 en0
10.255.1/24 10.255.1.65 UGSc 1 0 utun0
10.255.1.65 10.255.1.66 UH 3 0 utun0
10.255.99/24 10.255.99.49 UGSc 1 0 utun1
10.255.99.49 10.255.99.50 UH 13 0 utun1
10.255.100/24 10.255.100.41 UGSc 1 0 utun2
10.255.100.41 10.255.100.42 UH 13 0 utun2
111.202.124.222/32 192.168.1.1 UGSc 2 0 en0
127 127.0.0.1 UCS 1 0 lo0
127.0.0.1 127.0.0.1 UH 27 57535 lo0
169.254 link#4 UCS 1 0 en0
192.168.2 10.255.99.49 UGSc 1 0 utun1
192.168.3 10.255.99.49 UGSc 2 0 utun1
192.168.4 10.255.99.49 UGSc 1 0 utun1
192.168.7 10.255.99.49 UGSc 1 0 utun1
192.168.8 10.255.99.49 UGSc 1 0 utun1
192.168.89 10.255.99.49 UGSc 1 0 utun1
192.168.90 10.255.99.49 UGSc 1 0 utun1
192.168.91 10.255.99.49 UGSc 1 0 utun1
192.168.95 10.255.99.49 UGSc 1 0 utun1
192.168.99 10.255.99.49 UGSc 1 0 utun1
192.168.101 10.255.100.41 UGSc 1 0 utun2
192.168.103 10.255.100.41 UGSc 1 0 utun2
192.168.105 10.255.100.41 UGSc 2 0 utun2
192.168.110 10.255.100.41 UGSc 1 0 utun2
192.168.111 10.255.100.41 UGSc 1 0 utun2
192.168.168 10.255.1.65 UGSc 1 0 utun0
192.168.247 10.255.100.41 UGSc 1 0 utun2
192.168.248 10.255.100.41 UGSc 1 0 utun2
192.168.251 10.255.100.41 UGSc 1 0 utun2
192.168.252 10.255.100.41 UGSc 1 0 utun2
192.168.253 10.255.100.41 UGSc 1 0 utun2
224.0.0 link#4 UmCS 2 0 en0
224.0.0.251 1:0:5e:0:0:fb UHmLWI 1 0 en0
255.255.255.255/32 link#4 UCS 2 0 en0
255.255.255.255 link#4 UHLWbI 1 133 en0

添加路由

通过出口IP添加

1
2
3
4
route add -net 192.168.2.0/24 gw 192.168.10.85
route add -net 192.168.8.0/24 gw 192.168.10.85
route add -net 192.168.168.0/24 gw 192.168.10.85
route add -net 192.168.100.0/24 gw 192.168.10.85

通过出口设备添加

1
route add -net 0.0.0.0 dev ppp0 //添加默认路由

删除路由

1
2
3
4
route del -net 192.168.2.0/24 gw 192.168.10.85
route del -net 192.168.8.0/24 gw 192.168.10.85
route del -net 192.168.168.0/24 gw 192.168.10.85
route del -net 192.168.100.0/24 gw 192.168.10.85

使用ping x.x.x.x命令默认发送5个包

1
2
3
4
5
ciscoasa> ping 111.202.124.217
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 111.202.124.217, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/10 ms

可以指定发包的个数ping x.x.x.x repeat num

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ciscoasa> ping 111.202.124.217 repeat 100
Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 111.202.124.217, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 1/3/10 ms
ciscoasa> ping 111.202.124.217 repeat 1000
Type escape sequence to abort.
Sending 1000, 100-byte ICMP Echos to 111.202.124.217, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?!?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!?!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!
Success rate is 99 percent (992/1000), round-trip min/avg/max = 1/3/30 ms

后面还可给size 指定数据包的大小;timeout 表示超时的时间

配置MySQL从库,启动slave线程后”Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: ‘Could not find first log file name in binary log index file”的错误❌

  • step 1

先到slave中停止同步线程

1
mysql>  stop slave for channel "db136";  # mysql5.7多源复制的语法
  • step 2

回到master中,关闭当前的二进制日志文件并创建一个新文件,新的二进制日志文件的名字在当前的二进制文件的编号上加1

1
2
3
4
5
6
7
8
mysql> flush logs;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000038 | 154 | | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
  • step 3

再从slave执行change master

1
2
3
mysql> change master to master_host="192.168.1.136", master_port=3306, master_user="repl",master_password="12345678",master_log_file="mysql-bin.000038",master_log_pos=154 for channel "db136";
mysql> start slave for channel "db136";
mysql> show slave status for channel "db136";

MySQL多线程主从复制不是5.7版本中的新鲜产物,这个特性在5.6版本中就已经提供。但是在5.7版本中给多线程主从复制的特性做了增强

  • 在MySQL5.6版本中的多线程复制,前提是一个线程只针对一个库
  • 在MySQL5.7版本中,一个库可以使用多个线程同步,可以认为MySQL5.7的多线程复制是基于表的

多线程复制的配置

根据MySQL复制原理,可以知道,多线程复制只需要修改slave端即可

检查系统当前多线程复制的参数

1
2
3
4
5
6
7
8
9
10
mysql> show variables like 'slave_parallel%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| slave_parallel_type | DATABASE |
| slave_parallel_workers | 0 |
+------------------------+----------+
2 rows in set (0.01 sec)

mysql>

从上面的查询结果上来看,slave默认的多线程复制类型是基于数据库的,也就是一个数据库对应一个线程;而多线程复制的线程数量为0,意为单进程复制

设置多线程复制

1
2
3
4
5
6
7
8
9
10
11
12
13
mysql> stop slave;
Query OK, 0 rows affected (0.05 sec)

mysql> set global slave_parallel_type='logical_clock';
Query OK, 0 rows affected (0.00 sec)

mysql> set global slave_parallel_workers=8;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.18 sec)

mysql>

查看复制线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mysql> show processlist;
+----+-----------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
| 1 | event_scheduler | localhost | NULL | Daemon | 141366 | Waiting on empty queue | NULL |
| 13 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 14 | system user | | NULL | Connect | 49 | Waiting for master to send event | NULL |
| 15 | system user | | NULL | Connect | 48 | Slave has read all relay log; waiting for more updates | NULL |
| 16 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 17 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 18 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 19 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 20 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 21 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 22 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
| 23 | system user | | NULL | Connect | 49 | Waiting for an event from Coordinator | NULL |
+----+-----------------+-----------+------+---------+--------+--------------------------------------------------------+------------------+
12 rows in set (0.00 sec)

mysql> show variables like 'slave_parallel%';
+------------------------+---------------+
| Variable_name | Value |
+------------------------+---------------+
| slave_parallel_type | LOGICAL_CLOCK |
| slave_parallel_workers | 8 |
+------------------------+---------------+
2 rows in set (0.00 sec)

mysql>

注:MySQL5.7支持多源复制,这里的多线程复制的意思是为每一个源分配的多线程。例如上面我设置了线程数量为8,那意为着每个channel复制源都会提供8个线程去复制,如果有两个channel,那么在processlist中将看到16个线程

查看多线程复制相关的视图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mysql> show tables like 'replication%';
+---------------------------------------------+
| Tables_in_performance_schema (replication%) |
+---------------------------------------------+
| replication_applier_configuration |
| replication_applier_status |
| replication_applier_status_by_coordinator |
| replication_applier_status_by_worker |
| replication_connection_configuration |
| replication_connection_status |
| replication_group_member_stats |
| replication_group_members |
+---------------------------------------------+
8 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
mysql> select * from replication_applier_status_by_coordinator;
+--------------+-----------+---------------+-------------------+--------------------+----------------------+
| CHANNEL_NAME | THREAD_ID | SERVICE_STATE | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE | LAST_ERROR_TIMESTAMP |
+--------------+-----------+---------------+-------------------+--------------------+----------------------+
| db153 | 40 | ON | 0 | | 0000-00-00 00:00:00 |
+--------------+-----------+---------------+-------------------+--------------------+----------------------+
1 row in set (0.00 sec)

mysql>

注:由于MySQL5.7支持多源复制,那么这个复制的协调者replication_applier_status_by_coordinator会去协调每一个channel的复制线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select * from replication_applier_status_by_worker;
+--------------+-----------+-----------+---------------+-----------------------+-------------------+--------------------+----------------------+
| CHANNEL_NAME | WORKER_ID | THREAD_ID | SERVICE_STATE | LAST_SEEN_TRANSACTION | LAST_ERROR_NUMBER | LAST_ERROR_MESSAGE | LAST_ERROR_TIMESTAMP |
+--------------+-----------+-----------+---------------+-----------------------+-------------------+--------------------+----------------------+
| db153 | 1 | 41 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 2 | 42 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 3 | 43 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 4 | 44 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 5 | 45 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 6 | 46 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 7 | 47 | ON | | 0 | | 0000-00-00 00:00:00 |
| db153 | 8 | 48 | ON | | 0 | | 0000-00-00 00:00:00 |
+--------------+-----------+-----------+---------------+-----------------------+-------------------+--------------------+----------------------+
8 rows in set (0.00 sec)

mysql>

在这里可以清楚的看到,为db153这一个channel提供了8个复制线程,如果有两个channel的,这里将显示16行

MySQL5.7正式版本已经发布,在MySQL5.7中迎来了大幅的性能升级以及新的特性,本篇文章就来详细讨论下MySQL5.7的最新特性

MySQL服务功能增强

数据库初始化的方式变更

  • 在MySQL5.7版本之前,使用编译安装或使用二进制包部署MySQL,初始化的时候是使用了如下脚本来实现的
1
2
3
4
> /$path2mysql/script/mysql_install_db \
--datadir=/data/mysql \
--user=mysql
--basedir=/$path2mysql
  • 到了MySQL5.7,不再提供脚本的方式初始化数据库,而是改用mysqld程序的命令来实现
1
2
3
> mysqld --initialize --user=mysql \
--basedir=/$path2mysql
--datadir=/data/mysql

当然如果你使用了yum的方式安装了MySQL5.7,那么在第一次启动mysql的时候systemctl start mysqld默认会自动根据配置文件去初始化你的数据库

支持为表增加计算列

什么是计算列?

当一张表上的某一列的数据是由其他列的值计算得到的列,就称之为计算列

例如:一张表t,有c1,c2和c3列,c3的值=c1+c2

  • 在MySQL5.7之前,计算列只能通过触发器的方式来实现
1
2
3
4
mysql> create table t(id int auto_increment not null, c1 int, c2 int, c3 int, primary key (id));
Query OK, 0 rows affected (0.09 sec)

mysql>

这张表建立之后,向t表中的c1和c2插入数据,c3是不可能自动计算出来的

只能通过插入触发器来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> create trigger inst_t before insert on t for each row set new.c3=new.c1+new.c2; 
Query OK, 0 rows affected (0.07 sec)

mysql> show triggers;
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
| inst_t | INSERT | t | set new.c3=new.c1+new.c2 | BEFORE | 2016-08-21 01:52:06.01 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | root@localhost | utf8 | utf8_general_ci | utf8mb4_unicode_ci |
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
1 row in set (0.00 sec)

mysql> insert into t(c1, c2) values(1, 2);
Query OK, 1 row affected (0.11 sec)

mysql> select * from t;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 1 | 2 | 3 |
+----+------+------+------+
1 row in set (0.00 sec)

mysql>

上面实现了插入触发器,测试正常,但是一旦我去更改c1或c2的值,c3列是不会跟着变更的

因此还需要建立一个更新触发器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mysql> create trigger upd_t before update on t for each row set new.c3=new.c1+new.c2;
Query OK, 0 rows affected (0.08 sec)

mysql> show triggers;
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
| Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation |
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
| inst_t | INSERT | t | set new.c3=new.c1+new.c2 | BEFORE | 2016-08-21 01:52:06.01 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | root@localhost | utf8 | utf8_general_ci | utf8mb4_unicode_ci |
| upd_t | UPDATE | t | set new.c3=new.c1+new.c2 | BEFORE | 2016-08-21 02:01:50.46 | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | root@localhost | utf8 | utf8_general_ci | utf8mb4_unicode_ci |
+---------+--------+-------+--------------------------+--------+------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+----------------+----------------------+----------------------+--------------------+
2 rows in set (0.00 sec)

mysql> update t set c1=5 where id=1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from t;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 5 | 2 | 7 |
+----+------+------+------+
1 row in set (0.00 sec)

mysql>

从上面的Demo可以看出,在MySQL5.7之前,如果想实现计算列,只少要创建插入和更新两个触发器

而使用视图也是可以实现计算列的目的

1
2
3
4
5
6
7
8
9
10
11
12
mysql> create view vw_t as select id,c1,c2,c1+c2 as c3 from t;
Query OK, 0 rows affected (0.11 sec)

mysql> select * from vw_t;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 5 | 2 | 7 |
+----+------+------+------+
1 row in set (0.00 sec)

mysql>

而无论是使用触发器还是视图,对mysql的性能都会产生或多或少的影响,所以一般情况下,在生产环境中,建议是尽可能少的使用触发器和视图

  • 在MySQL5.7原生支持计算列语法

create table以及alter table语句中支持增加计算列

col_name data_type [GENERATED ALWAYS] AS (expression) [VIRTUAL|STORED] [UNIQUE [KEY]] [COMMENT comment] [[NOT] NULL] [[PRIMARY] KEY]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
mysql> drop table t;
Query OK, 0 rows affected (0.25 sec)

mysql> create table t (id int auto_increment not null, c1 int, c2 int, c3 int as (c1+c2), primary key(id));
Query OK, 0 rows affected (0.22 sec)

mysql> show create table t;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`c1` int(11) DEFAULT NULL,
`c2` int(11) DEFAULT NULL,
`c3` int(11) GENERATED ALWAYS AS ((`c1` + `c2`)) VIRTUAL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> insert into t(c1, c2) values(1, 2);
Query OK, 1 row affected (0.05 sec)

mysql> select * from t;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 1 | 2 | 3 |
+----+------+------+------+
1 row in set (0.00 sec)

mysql> update t set c1=9 where id=1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0

mysql> select * from t;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 9 | 2 | 11 |
+----+------+------+------+
1 row in set (0.00 sec)

mysql>

MySQL5.7原生支持的计算列有两种模式,一种是虚拟列,一种是存在磁盘中的列。虚拟列不占用磁盘空间

引入了JSON列类型及相关的函数

  • MySQL5.7之前,只能在varchar或是text等字符类型的列中存储json类型的字符串,并通过程序解析来使用json字符串
  • MySQL5.7之后,增加了json列类型以及json_开头的相关处理函数,如json_type()``json_object()``json_merge()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 生成一个json的数组
mysql> select json_array('a','b',now());
+------------------------------------------+
| json_array('a','b',now()) |
+------------------------------------------+
| ["a", "b", "2016-08-21 02:41:45.000000"] |
+------------------------------------------+
1 row in set (0.00 sec)

# 生成一个json KV对象
mysql> select json_object('k1',1,'k2',2);
+----------------------------+
| json_object('k1',1,'k2',2) |
+----------------------------+
| {"k1": 1, "k2": 2} |
+----------------------------+
1 row in set (0.00 sec)

创建一个含有json类型字段的表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
mysql> create table t1(jdoc json);
Query OK, 0 rows affected (0.32 sec)

mysql> show create table t1;
+-------+-------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
`jdoc` json DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
+-------+-------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> insert into t1(jdoc) values(json_array('a','b',now()));
Query OK, 1 row affected (0.05 sec)

mysql> insert into t1(jdoc) values(json_object('k1',1,'k2',2));
Query OK, 1 row affected (0.06 sec)

mysql> select * from t1;
+------------------------------------------+
| jdoc |
+------------------------------------------+
| ["a", "b", "2016-08-21 02:47:50.000000"] |
| {"k1": 1, "k2": 2} |
+------------------------------------------+
2 rows in set (0.00 sec)

mysql>

REPLICATION方面的增强

支持多源复制

基于库或是逻辑锁的多线程复制

在线变更复制方式

InnoDB存储引擎的增强

支持缓冲池大小在线变更

增加innodb_buffer_pool导入导出功能

支持为innodb表建立表空间

MySQL安全方面的增强

初始化数据库后的默认密码

  • 在MySQL5.7之前的版本,初始化数据库后,默认的root密码为空,在localhost直接使用mysql客户端,可以以无密码的方式进入到数据库中

  • 在MySQL5.7中,在初始化数据库之后,会为root生成一个强度为大写字母+小写字母+数字+特殊符号的密码,并且首次进入到mysql时,强制要你更改密码,且强度默认依然为大写字母+小写字母+数字+特殊符号

关于MySQL5.7的初始化密码的查找,可以参考本站的文章

默认的密码强度

mysql对于密码有3种检验策略,默认validate_password_policy为MEDIUM

  • LOW policy tests password length only. Passwords must be at least 8 characters long.
  • MEDIUM policy adds the conditions that passwords must contain at least 1 numeric character, 1 lowercase and uppercase character, and 1 special (nonalphanumeric) character.
  • STRONG policy adds the condition that password substrings of length 4 or longer must not match words

关于MySQL5.7密码强度的更改,可以参考本站的文章

不在支持old_password认证

增加账号默认过期时间

加强了对账号的管理功能

增加了sys管理数据库