Rao's Blog

  • 首页

  • 标签

  • 分类

  • 归档

  • 搜索

MySQL · 安装

发表于 2019-07-17 | 更新于 2020-08-05 | 分类于 MySQL

MySQL 5.7

  • 创建用户
1
2
groupadd mysql
useradd -g mysql mysql -s /sbin/nologin
  • 下载二进制包
1
2
3
wget http://devops-files.oss-cn-qingdao.aliyuncs.com/mysql-5.7.23-linux-glibc2.12-x86_64.tar.gz
tar -zxvf mysql-5.7.23-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
ln -s /usr/local/mysql-5.7.23-linux-glibc2.12-x86_64 /usr/local/mysql
  • 配置文件 my.cnf
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
[client]
port = 3306
socket = /data/mysql/mysql.sock

[mysqld]
port = 3306
socket = /data/mysql/mysql.sock
pid_file = /data/mysql/mysql.pid
basedir = /usr/local/mysql
datadir = /data/mysql
character_set_server = utf8

# LOG
slow_query_log = 1
long_query_time = 3
log_error = /data/mysql/error.log
slow_query_log_file = /data/mysql/slow.log
log_queries_not_using_indexes = 1
sync_binlog = 0
innodb_flush_log_at_trx_commit = 0

# INNODB
innodb_buffer_pool_size = 10240M
innodb_buffer_pool_instances = 4
innodb_data_home_dir = /data/mysql
innodb_log_file_size = 1G
innodb_data_file_path = ibdata1:1G:autoextend
innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:5G

# OTHER
max_connections = 3000
back_log = 1024
interactive_timeout = 600
wait_timeout = 600
lower_case_table_names = 1
log_timestamps = SYSTEM
max_allowed_packet = 32M
sort_buffer_size = 4M
join_buffer_size = 4M
tmp_table_size = 32M
explicit_defaults_for_timestamp = 1
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
skip-ssl
skip-name-resolve

# REPLICATION
server-id = 3306100
log-bin = /data/mysql/mysql-bin
max_binlog_size = 1G
binlog-format = row
expire_logs_days = 7

[mysqldump]
quick
max_allowed_packet = 32M
  • 创建数据目录
1
2
3
mkdir -p /data/mysql
chown -R mysql:mysql /usr/local/mysql
chown -R mysql:mysql /data/mysql
  • 初始化 & 启动
1
2
/usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf --user=mysql --initialize
/usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql 2>&1> /dev/null &
  • 开启 3306 端口
1
2
firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload
  • 设置开机自启动
1
2
3
4
5
6
7
8
9
cd /usr/local/mysql/bin
cp mysql mysqladmin mysqlbinlog mysqld mysqld_safe mysqldump /usr/bin/

vi /usr/local/mysql/support-files/mysql.server # mysqld_pid_file_path=/data/mysql/mysql.pid
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chmod +x /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
chkconfig --list
  • 设置用户
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cat /data/mysql/error.log | grep password

# root
mysql> SET PASSWORD = 'xx';
mysql> ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;

# sre
mysql> CREATE USER 'sre'@'%' IDENTIFIED BY 'xx';
mysql> GRANT all privileges on *.* to 'sre'@'%' WITH GRANT OPTION;

# hdm
mysql> CREATE USER 'hdm'@'%' IDENTIFIED BY 'xx';
mysql> GRANT SELECT, SHOW DATABASES, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'hdm'@'%';

mysql> flush privileges;
mysql> select user,host,authentication_string from mysql.user;

MySQL 5.6

  • 初始化
1
/usr/local/mysql/scripts/mysql_install_db --basedir=/usr/local/mysql --defaults-file=/etc/my.cnf --user=mysql
  • 启动
1
$ /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf --user=mysql 2>&1 > /dev/null &
  • 设置用户
1
2
3
4
5
mysql
mysql> update mysql.user set password=password('xx') where user='root';
mysql> delete from mysql.user where user!='root' or host!='localhost';
mysql> flush privileges;
mysql> select user,host,password from mysql.user;

配置主从

  • 创建用户
1
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'repl'@'x.x.x.%' IDENTIFIED BY 'xx';
  • 修改从库 my.cnf 文件
1
2
3
4
5
server_id         = 3306101
log_bin = mysql-bin
relay_log = relay-log
read_only = 1
log_slave_updates = 1
  • 传输数据至从库
  • 配置复制
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
# 主库查看日志和位置
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000002 | 3778 | | | |
+------------------+----------+--------------+------------------+-------------------+

# 从库配置复制
CHANGE MASTER TO
MASTER_HOST='x.x.x.x',
MASTER_USER='repl',
MASTER_PASSWORD='xx',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=3778;

# 验证
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.138.98.179
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000002
Read_Master_Log_Pos: 3778
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 1621
Relay_Master_Log_File: mysql-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...

启停

停止

  • 使用 init.d,mysqld 脚本来自于 /usr/local/mysql/support-files/mysql.server
1
$ /etc/init.d/mysqld stop
  • 使用 mysqladmin
1
$ mysqladmin -u'xx' -p'xx' shutdown
  • 使用 service
1
2
$ systemctl stop mysqld
$ service mysqld stop

启动

  • 使用 init.d
1
$ /etc/init.d/mysqld start
  • 使用 mysqld_safe
1
$ mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &
  • 使用 service
1
2
$ systemctl start mysqld
$ service mysqld start

工具命令

  • mysql:MySQL 客户端访问管理工具。

  • mysqld:这个可执行文件就代表着 MySQL 服务器程序,运行这个可执行文件就可以直接启动一个服务器进程。

  • mysqld 启动配置文件优先级:

  • 1
    /etc/my.cnf -> /etc/mysql/my.cnf -> /usr/etc/my.cnf -> ~/.my.cnf
  • mysqld_safe:是一个启动脚本,它会间接的调用 mysqld,而且还顺便启动了另外一个监控进程,这个监控进程在服务器进程挂了的时候,可以帮助重启它。使用 mysqld_safe 启动 mysqld 时,mysqld_safe 可以使用参数选项,此时可以使用其他配置文件,相当于 mysqld_safe 把参数传递给 mysqld。

  • mysql.server:也是一个启动脚本,主要作用就是为了方便启动和关闭 mysqld 服务,只能使用默认的 /etc/my.cnf 配置文件,mysql.server 调用 mysqld_safe,然后 mysql_safe 调用了 mysqld。

FAQ

现象:使用 mysqld_safe 启动失败,启动错误日志未记录 error.log,报错如下:

1
Starting MySQL. ERROR! The server quit without updating PID file (/usr/local/mysql/data/COSMOPlat-WMS-App01.pid)

原因:经检查发现,数据库安装时是以 haieradmin 用户启动,默认使用 mysql 用户启动,启动失败。

解决:使用 haieradmin 用户启动成功。

安装脚本 mysql_install.sh

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/bin/bash

# ###########################################################################
# MySQL安装包名字为mysql-5.7.23-el7-x86_64.tar.gz,位置放在/usr/local/
# ###########################################################################

cmd=$2 # start or stop or status or install
inst=$4

service_startup_timeout=30

log_failure_msg() {
echo " ERROR! $@"
}

log_success_msg() {
echo " SUCCESS! $@"
}

case `echo "testing\c"`,`echo -n testing` in
*c*,-n*) echo_n= echo_c= ;;
*c*,*) echo_n=-n echo_c= ;;
*) echo_n= echo_c='\c' ;;
esac

wait_for_pid () {
verb="$1" # created | removed
pid="$2" # process ID of the program operating on the pid-file
pid_file_path="$3" # path to the PID file.

i=0
avoid_race_condition="by checking again"

while test $i -ne $service_startup_timeout ; do

case "$verb" in
'created')
# wait for a PID-file to pop into existence.
test -s "$pid_file_path" && i='' && break
;;
'removed')
# wait for this PID-file to disappear
test ! -s "$pid_file_path" && i='' && break
;;
*)
echo "wait_for_pid () usage: wait_for_pid created|removed pid pid_file_path"
exit 1
;;
esac

if test -n "$pid"; then
if kill -0 "$pid" 2>/dev/null; then
:
else
if test -n "$avoid_race_condition"; then
avoid_race_condition=""
continue
fi

log_failure_msg "The server quit without updating PID file ($pid_file_path)."
return 1
fi
fi

echo $echo_n ".$echo_c"
i=`expr $i + 1`
sleep 1

done

if test -z "$i" ; then
log_success_msg
return 0
else
log_failure_msg
return 1
fi
}

# ############################################################################################
# 支持MySQL版本:5.6/5.7,CentOS 6系统建议安装MySQL 5.6版本;CentOS 7系统建议安装MySQL 5.7版本
# 支持MySQL模式:单机/主从
# #############################################################################################

install_mysql() {

echo $echo_n "Installing MySQL..."

local basedir="/usr/local/mysql"
local datadir="/data/mysql"
local defaults_file="/etc/my.cnf"
local sock_file="$datadir/mysql.sock"
local pid_file="$datadir/mysql.pid"
local array=(${inst//@/ })
local port=${array[1]}

# 创建MySQL用户,指定MySQL所在的用户组
groupadd mysql >/dev/null 2>&1
useradd -g mysql mysql -s /sbin/nologin >/dev/null 2>&1

# 解压MySQL软件包,并对mysql目录授权
cd /usr/local
tar -zxvf mysql-5.7.23-el7-x86_64.tar.gz >/dev/null 2>&1
ln -s mysql-5.7.23-el7-x86_64 mysql
chown mysql:mysql -R mysql
chown mysql:mysql -R mysql-5.7.23-el7-x86_64

# 创建数据目录
mkdir -p $datadir
chown mysql:mysql -R $datadir

# 初始化数据库
cd /usr/local/mysql/bin
./mysqld --defaults-file="$defaults_file" --basedir="$basedir" --datadir="$datadir" --user=mysql --initialize-insecure >/dev/null 2>&1

# 启动数据库
./mysqld_safe --defaults-file="$defaults_file" --pid-file="$pid_file" --user=mysql >/dev/null &
wait_for_pid created "$!" "$pid_file"; return_value=$?

# 打开防火墙端口
firewall-cmd --permanent --zone=public --add-port=3306/tcp >/dev/null 2>&1
firewall-cmd --reload >/dev/null 2>&1

cp mysql* /usr/bin >/dev/null 2>&1
# mv /usr/local/mysql_tool /usr/bin >/dev/null 2>&1
mysql -S $sock_file mysql -e "SET PASSWORD = 'xx';ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;flush privileges;"
mysql -S $sock_file mysql -e "SET PASSWORD = 'xx';ALTER USER 'hdm'@'%' PASSWORD EXPIRE NEVER;flush privileges;"
mysql -S $sock_file mysql -e "SET PASSWORD = 'xx';ALTER USER 'sre'@'%' PASSWORD EXPIRE NEVER;flush privileges;"
exit $return_value
}

case "$cmd" in
'install') install_mysql ;;
'uninstall') mysql_uninstall ;;
'start') mysql_start ;;
'stop') mysql_stop ;;
'restart') mysql_restart ;;
'config') mysql_config ;;
'monitor') mysql_monitor ;;
*)
# usage
basename=`basename "$0"`
echo "Usage: $basename -cmd {start|stop|restart|install|uninstall|status|monitor} -inst {instance name} [ MySQL tool options ]"
exit 1
;;
esac
exit 0

MySQL · 案例集锦

发表于 2019-07-15 | 更新于 2020-09-17 | 分类于 MySQL

系列

  • MySQL · 案例分析 · 主从复制中断
  • MySQL · 案例分析 · 磁盘空间不足
  • MySQL · 案例分析 · information_schema.tables 与 count(*) 查询数不一致

数据库连接失败

问题现象

项目经理火急火燎的反馈,说数据库连接不上了,请求排查问题原因。

原因分析

  • 测试 Navicate 是否能够连上数据库 ?

  • 登录服务器,查看 mysqld 进程是否存在,如果进程不存在,可能是服务器断电导致进程未自启动。

1
2
3
4
5
6
$ ssh -p 2222 01510886@10.138.16.192

$ ps -ef | grep mysqld
root 64511 64440 0 10:27 pts/2 00:00:00 grep --color=auto mysqld
root 79355 1 0 Aug31 ? 00:00:00 /bin/sh /usr/local/mysql/bin/mysqld_safe --datadir=/data/mysql --pid-file=/data/mysql/mysql.pid
mysql 79981 79355 99 Aug31 ? 2-01:38:14 /usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/mysql --plugin-dir=/usr/local/mysql/lib/plugin --user=mysql --log-error=/data/mysql/error.log --pid-file=/data/mysql/mysql.pid --socket=/data/mysql/mysql.sock --port=3306
  • 登录 mysql,查看线程状态,查看是否有锁占用,或者线程大量阻塞情况。
1
2
$ mysql -S /data/mysql/mysql.sock -usre -p'sre@@p$i'
mysql> show processlist;

解决方法

  • 如果是第一种原因,启动 mysql 进程
1
2
3
4
5
$ cd /etc/init.d
$ ./mysqld stop/start

$ cd /usr/local/mysql/support-files
$ ./mysql.server stop/start
  • 如果是第二种原因,删除正在执行的锁表线程
1
2
3
4
5
# 杀掉ID为1的线程, 关闭连接
kill id;

# 查询出时间大于10的线程, 复制查询结果,批量执行
select concat('kill ', id, ';') from information_schema.processlist where time > 10;

备份夯住

现象描述

据备份供应商反映,昨天晚上 22:00 XX系统,从库备份失败,使用的备份工具是 mysqldump,请求协助定位备份失败原因。

原因分析

(1)检查从库两个线程 Slave_IO_Running 和 Slave_SQL_Running 均是 Yes,说明主从复制链路正常,但是 Seconds_Behind_Master 不断增大,且主从数据延迟有不断扩大的趋势。

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
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.133.0.51
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-binlog.000232
Read_Master_Log_Pos: 3108253
Relay_Log_File: relay-log.000004
Relay_Log_Pos: 169851605
Relay_Master_Log_File: mysql-binlog.000229
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 169851386
Relay_Log_Space: 3270427001
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 42302
Master_SSL_Verify_Server_Cert: No
....

1 row in set (0.00 sec)

(2)检查当前数据库线程状态,未发现有明显异常。

1
2
3
4
5
6
7
8
9
10
mysql> show processlist;
+-------+-------------+-------------------+--------------------+---------+--------+----------------------------------+--------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+-------+-------------+-------------------+--------------------+---------+--------+----------------------------------+--------------------------------+
| 1 | system user | | NULL | Connect | 172777 | Waiting for master to send event | NULL |
| 2 | system user | | NULL | Connect | 678456 | Reading event from the relay log | NULL |
| 4345 | cvbak | localhost | NULL | Query | 130546 | Waiting for table flush | FLUSH /*!40101 LOCAL */ TABLES |
| 17662 | root | localhost | NULL | Query | 0 | starting | show processlist |
| 17671 | hdm | 10.133.0.52:37170 | information_schema | Sleep | 1 | | NULL |
+-------+-------------+-------------------+--------------------+---------+--------+----------------------------------+--------------------------------+

(3)检查当前正在使用的表:show open tables where In_use=1; 发现有一张表一直处于 In_use 状态。

1
2
3
4
5
6
7
mysql> show open tables where In_use=1;
+----------+---------------------------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+---------------------------+--------+-------------+
| tdmetl | odsepg_zrfc_zco_zzfymx_sw | 1 | 0 |
+----------+---------------------------+--------+-------------+
1 row in set (0.00 sec)

(4)根据 Relay_Log_Pos 解析 relay-log.000004,查看当时正在执行的操作是 Delete_rows,操作的表是 tdmetl.odsepg_zrfc_zco_zzfymx_sw。

1
# mysqlbinlog -vv --base64-output=decode-rows relay-log.000004 --start-position=169851605 | more
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
# at 169851605
#190718 4:02:58 server id 3306100 end_log_pos 169851451 CRC32 0x6683bf99 Anonymous_GTID last_committed=1831 sequence_number=1832 rbr_
only=yes
/*!50718 SET TRANSACTION ISOLATION LEVEL READ COMMITTED*//*!*/;
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;

# at 169851670
#190718 4:02:58 server id 3306100 end_log_pos 169851525 CRC32 0x9d910e5d Query thread_id=1254417 exec_time=0 error_code=0
SET TIMESTAMP=1563393778/*!*/;
SET @@session.pseudo_thread_id=1254417/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1436549128/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;

# at 169851744
#190718 4:02:58 server id 3306100 end_log_pos 169851626 CRC32 0x6b8bbd2d Table_map: `tdmetl`.`odsepg_zrfc_zco_zzfymx_sw` mapped to number 170
018

# at 169851845
#190718 4:02:58 server id 3306100 end_log_pos 169859832 CRC32 0x338e105a Delete_rows: table id 170018

(5)检查表结构,发现该表数据量很大且无主键。由此基本确定其问题根本原因:对无主键的表进行删除或者更新,导致从库夯住。该表数据量:77961221条。

image-20190822092437992

解决方法

(1)表添加自增主键。

1
ALTER TABLE 'xxxx' ADD id int UNSIGNED primary key AUTO_INCREMENT;

(2)大表删除使用 truncate 命令。

建议

  • 避免无 where 条件的 delete 或 update 操作大表,如果需要全表删除,使用 truncate 操作。
  • 在 binlog row 模式下表结构最好能有主键。

主从复制中断

问题现象

监控系统,检测到xx项目主从复制中断,并发送了告警

原因分析

1)登录所报告警数据库,查看复制状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ssh haieradmin@10.138.8.216
ssh root@10.159.37.148
ssh haieradmin@10.159.44.168

MariaDB [(none)]> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.133.8.96
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.002660
Read_Master_Log_Pos: 343075905
Relay_Log_File: relay-log-bin.003429
Relay_Log_Pos: 555
Relay_Master_Log_File: mysql-bin.001741
Slave_IO_Running: Yes
Slave_SQL_Running: No

经检查 Slave_SQL_Running 为 No,原因一般都很明显,记录在 Last_Error,根据报错原因选择合适地解决方法,最常用的解决办法是跳过这一条正在执行的 SQL。

解决方法

(1)登陆 10.133.0.53

(2)执行下面操作

1
2
3
4
5
6
pt-slave-restart -h 'x.x.x.x' -u'xx' -p'xx' -P 3306

#一般是事务回滚造成的
stop slave;
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
start slave;
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
mysql> show slave status\G
************************* 1. row ***************************
Slave_IO_State:
Master_Host: 10.135.22.70
Master_User: repluser
Master_Port: 3308
Connect_Retry: 10
Master_Log_File: mysql-bin.001935
Read_Master_Log_Pos: 6587
Relay_Log_File: relay-log.001487
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.001935
Slave_IO_Running: No
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table: test.%
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 6587
Relay_Log_Space: 107
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 1236
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'
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
1
2
3
Slave_IO_Running: No
Slave_SQL_Running: Yes
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'
1
2
3
4
5
6
7
8
9
10
11
12
[root@hop02 mzjh]# ll | grep mysql-bin
-rw-rw----. 1 mysql mysql 1073742013 Sep 12 14:55 mysql-bin.001948
-rw-rw----. 1 mysql mysql 1073742073 Sep 13 11:53 mysql-bin.001949
-rw-rw----. 1 mysql mysql 1073742120 Sep 14 08:39 mysql-bin.001950
-rw-rw----. 1 mysql mysql 1073859355 Sep 15 06:21 mysql-bin.001951
-rw-rw----. 1 mysql mysql 1074054892 Sep 16 06:18 mysql-bin.001952
-rw-rw----. 1 mysql mysql 1075243641 Sep 17 06:18 mysql-bin.001953
-rw-rw----. 1 mysql mysql 1074801420 Sep 18 06:16 mysql-bin.001954
-rw-rw----. 1 mysql mysql 1075257243 Sep 19 06:16 mysql-bin.001955
-rw-rw----. 1 mysql mysql 619405162 Sep 19 13:32 mysql-bin.001956
-rw-rw----. 1 mysql mysql 1072898197 Sep 20 09:44 mysql-bin.001957
-rw-r-----. 1 mysql mysql 190 Sep 19 13:32 mysql-bin.index

从库在主库找不到 binlog 文件

原因

该错误发生在从库的io进程从主库拉取日志时,发现主库的mysql_bin.index文件中第一个文件不存在。出现此类报错可能是由于你的slave 由于某种原因停止了好长一段是时间,当你重启slave 复制的时候,在主库上找不到相应的binlog ,会报此类错误。或者是由于某些设置主库上的binlog被删除了,导致从库获取不到对应的binglog file。

表碎片

表碎片是 MySQL 运维过程中比较常见的问题,碎片的存在十分影响数据库的性能。

判断方法

MySQL 的碎片是否产生,通过查看

1
show table status from table_name\G;

这个命令中 Data_free 字段,如果该字段不为 0,则产生了数据碎片。

产生原因

1. 经常进行 delete 操作

经常进行 delete 操作,产生空白空间,如果进行新的插入操作,MySQL 将尝试利用这些留空的区域,但仍然无法将其彻底占用,久而久之就产生了碎片;

2. update 更新

update 更新可变长度的字段(例如:varchar 类型),将长的字符串更新成短的。之前存储的内容长,后来存储是短的,即使后来插入新数据,那么有一些空白区域还是没能有效利用的。

产生影响

  1. 由于碎片空间是不连续的,导致这些空间不能充分被利用;

  2. 由于碎片的存在,导致数据库的磁盘 I/O 操作变成离散随机读写,加重了磁盘 I/O 的负担。

清理办法

  • MyISAM:optimize table 表名;(OPTIMIZE 可以整理数据文件,并重排索引)

  • InnoDB:

    (1)重建表存储引擎:ALTER TABLE tablename ENGINE = InnoDB;

    (2)进行一次数据的导入导出

碎片清理的性能对比:

引用我之前一个生产库的数据,对比一下清理前后的 SQL 执行速度差异:

1
2
3
select count(*) from test.twitter_11;
修改前:1 row in set (7.37 sec)
修改后:1 row in set (1.28 sec)

总结

通过对比,可以看到碎片清理前后,节省了很多空间,SQL执行效率更快。所以,在日常运维工作中,应该对表碎片进行定期清理,保证数据库有稳定的性能。

触发器创建失败

问题现象

创建触发器,报错提示”1419”

1
2
ERROR 1419 (HY000): You do not have the SUPER privilege and
binary logging is enabled (you *might* want to use the less safe log_bin_trust_routine_creators variable)

原因分析

有些操作要禁止掉对 SUPER 权限的要求,要处理可以设置 log_bin_trust_routine_creators 全局系统变量为 1,默认地,这个变量值为 0。

解决方法

直接在数据库进行修改,也可以在启动服务器之时用 --log-bin-trust-routine-creators 选项来设置允许这个变量。

1
mysql> SET GLOBAL log_bin_trust_routine_creators = 1;

MySQL · 知识体系养成计划

发表于 2019-07-12 | 更新于 2020-08-10 | 分类于 MySQL

入门篇

  • MySQL · 发展历程
  • MySQL · 安装
  • MySQL · 连接
  • MySQL · 体系结构
  • MySQL · 文件
  • MySQL · 权限

基础篇

进阶篇

国产数据库的演进历史

发表于 2019-07-12 | 更新于 2019-11-15 | 分类于 数据库

1949-1979

  • 1956年,周恩来总理亲自领导了“科学技术发展十二年规划”,标志着我国计算机事业的开始。

中国仿制前苏联大型机

  • 随后十年动乱,中国计算机和数据库的研究基本停滞成为空白。
  • 70年代末,关系型数据库的概念刚刚兴起,1975年微软成立,1977年 Oracle 成立(70年代是美国的黄金年代)。OLTP 联机交易处理也称为面向交易的处理过程让数据库变得重要起来,也就是说计算机不但承担的是结果的纯计算,现在要实时承担交易过程和结果记录。

1979-1989

  • 1977年,中国人民大学萨师煊教授和王珊教授编著《数据库系统概论》,并召开数据库年会。

  • 80年代,中美正式建交,中国信息技术建设开始和世界开始接轨。自动化还没上马,信息化更是难寻踪迹,在数据库的研发和投入上,靠的是零星的科研力量和资金。这个时期,产、学、研是三条平行线。

主流关系型数据库家谱图

1989-1999

  • 80年代以研究所和大学为主的国家投入,那么在90年代产出这样几家国产数据库公司

90年代863研究计划

1999-2009

90年代,改革开放掀起的热潮,开始了外资和中国市场合作的黄金十年,外资在我国空前发展阶段,Oracle 和 DB2 横扫市场所有产品。在中国数据库公司刚刚成立想开发产品追赶 Oracle 的时候,市场的需求已经迸发出来,国产产品接不住,所以市场就是 Oracle 的天下了。这样出现了死循环:

  • 产品初期需要不断的试错和验证的机会。
  • 客户没有时间和办法陪着试错和成长。
  • 没有客户,生态就更差,更没有办法进行产品的投入和迭代。

2009-2019

互联网崛起的这十年,国内数据库厂商:

db

去IOE:IBM 小型机、Oracle 数据库、EMC 存储设备

取代品:X86 服务器、MySQL 数据库、分布式存储

IBM大型机:IBM Z系列,目前市场无性能相当替代品,国家民生、银行电信等关键核心业务

big

小型机:UNIX 服务器,IBM 的 POWER 处理器 + AIX 操作系统,RAS(Reliability, Availability,Serviceability 高可靠性、高可用性、高服务性)特性。解决方案从处理器到平台、操作系统、中间件,再到应用软件,都出于自家门下。好处就是各层次之间能有一个较好的优化和配合,让用户在从采购到部署、再到应用和维护的过程中无需自己太过操心。反过来说,这种模式使得用户容易被厂商锁定,后续IT系统采购、维护和应用,全部处于被垄断后的弱势地位,采购后的维护和更新也只能被动接受。

small

x86 服务器:成本低、易扩展、易维护更新

x86

  • ARM 架构:广泛适用于移动端,优点是低功耗。
  • x86 架构:广泛用于 PC 端,便宜、易扩展、易集成第三方软件。

中国 IT 信息技术的崛起

it信息技术

国内工业级应用软件发展

it信息技术

服务器演进

服务器

MySQL · 性能优化

发表于 2019-07-11 | 更新于 2020-08-13 | 分类于 MySQL

简介

用户首先需要清楚当前数据库的应用类型。一般而言,可分为两类:

  • OLTP(Online Transaction Processing,在线事务处理):多用在日常事务处理应用中。一般用户操作的并发量大、复杂的查询较少。OLTP 是 IO 密集型操作,需要将更多注意力放在提高 IO 的配置上。
  • OLAP(Online Analytical Processing,在线分析处理):多用在数据库仓库、集市中,一般需要执行复杂的 SQL 语句进行查询。复杂的查询如排序、连接、比较等非常消耗 CPU,需要将注意力放在提高 CPU 的配置上。

MySQL 优化思路:

  • 优化成本:硬件配置 > 架构优化 > MySQL 配置参数 > 表结构与索引
  • 优化效果:表结构与索引 > MySQL 配置参数 > 架构优化 > 硬件配置

硬件优化

  • 硬盘,固态硬盘 SSD > 机械硬盘 HDD。
  • 内存,内存的大小直接影响数据库的性能,MySQL 内存一般设置为物理内存大小的 80%。
  • RAID(独立磁盘冗余数组),基本思想就是把多个相对便宜的硬盘组合起来,成为一个磁盘数组,使性能达到甚至超过一个价格昂贵、容量巨大的硬盘。RAID 0 性能最高、可靠性最低,RAID 1 可靠性最高、性能最低。对于数据库应用来说,RAID 10 是最好的选择,它同时兼顾了 RAID 1 和 RAID 0 的特性。

架构优化

  • 加缓存
  • 分库分表
  • 读写分离

配置参数优化

  • innodb_buffer_pool_size
  • max_connections
  • innodb_flush_log_at_trx_commit
  • sync_binlog
  • binlog_cache_size
  • innodb_log_file_size

表结构与索引优化

  • 主键

  • 选择合适的数据类型,例如:datetime vs timestamp、varchar vs char

  • SQL 改写,例如: select *、模糊匹配 like 等

  • 紧急调优方法,查看实时会话,show processlist

  • 常规调优方法,分析慢查询日志,利用工具 pt-query-digest

  • 执行计划,调整索引

    • select_type:查询类型(SIMPLE - 简单查询、PRIMARY - 主查询、UNION - 并集、SUBQUERY - 子查询)。

    • table:输出结果集的表。

    • type:访问类型(ALL - 全表查询性能最差、index、range、ref、eq_ref、const、NULL)。

    • possible_keys:查询时可能用到的索引。

    • key:实际使用的索引。

    • key_len:索引字段的长度。

    • rows:扫描的行数,行数越少肯定性能越好。

    • extra:额外信息。

基准测试工具

sysbench

是一个模块化的、跨平台的多线程基准测试工具,主要用于测试各种不同系统参数下的数据库负载情况。主要包括以下几种测试方式:

  • CPU 性能
  • 磁盘 IO 性能
  • 数据库 OLTP 基准测试

CentOS 安装

1
2
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
sudo yum -y install sysbench

前端学习笔记

发表于 2019-07-10 | 更新于 2020-01-07 | 分类于 前端

学习路径

前端技能图谱

如何搭建 一个 vue 项目?

安装 node 环境

下载 Node.js

1
2
3
4
5
$ node -v
v10.15.3

$ npm -v
6.10.0

安装淘宝镜像,提高效率

1
2
3
$ npm install -g cnpm --registry=https://registry.npm.taobao.org
C:\Users\01510886\AppData\Roaming\npm\cnpm -> C:\Users\01510886\AppData\Roaming\npm\node_modules\cnpm\bin\cnpm
+cnpm@6.1.0
1
2
3
4
5
6
7
8
$ cnpm -v
cnpm@6.1.0 (C:\Users\01510886\AppData\Roaming\npm\node_modules\cnpm\lib\parse_argv.js)
npm@6.10.0 (C:\Users\01510886\AppData\Roaming\npm\node_modules\cnpm\node_modules\npm\lib\npm.js)
node@10.15.3 (D:\software\nodejs\node.exe)
npminstall@3.22.1 (C:\Users\01510886\AppData\Roaming\npm\node_modules\cnpm\node_modules\npminstall\lib\index.js)
prefix=C:\Users\01510886\AppData\Roaming\npm
win32 x64 6.1.7601
registry=https://r.npm.taobao.org

搭建 vue 项目环境

安装 vue-cli

1
2
3
4
5
6
7
8
9
10
$ npm install --global vue-cli

$ vue list
Available official templates:
★ browserify - A full-featured Browserify + vueify setup with hot-reload, linting & unit testing.
★ browserify-simple - A simple Browserify + vueify setup for quick prototyping.
★ pwa - PWA template for vue-cli based on the webpack template
★ simple - The simplest possible Vue setup in a single HTML file
★ webpack - A full-featured Webpack + vue-loader setup with hot reload, linting, testing & css extraction.
★ webpack-simple - A simple Webpack + vue-loader setup for quick prototyping.

创建一个基于 webpack 模板的新项目

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
57
58
59
60
61
62
63
64
65
66
67
68
69
$ vue init webpack vue-test

? Project name (vue-test)
? Project name vue-test
? Project description (A Vue.js project)
? Project description A Vue.js project
? Author (raohui <raohui@haier.com>)
? Author raohui <raohui@haier.com>
? Vue build standalone
? Install vue-router? (Y/n) Y
? Install vue-router? Yes
? Use ESLint to lint your code? (Y/n) n
? Use ESLint to lint your code? No
? Set up unit tests (Y/n) n
? Set up unit tests No
? Setup e2e tests with Nightwatch? (Y/n) n
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recom
? Should we run `npm install` for you after the project has been created? (recom
mended) npm

vue-cli · Generated "vue-test".


# Installing project dependencies ...
# ========================

npm WARN deprecated extract-text-webpack-plugin@3.0.2: Deprecated. Please use https://github.com/webpack-contrib/mini-css-extract-plugin
npm WARN deprecated browserslist@2.11.3: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.
npm WARN deprecated bfj-node4@5.3.1: Switch to the `bfj` package for fixes and new features!
npm WARN deprecated flatten@1.0.2: I wrote this module a very long time ago; you should use something else.
npm WARN deprecated browserslist@1.7.7: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools.

> core-js@2.6.9 postinstall D:\vue\vue-test\node_modules\core-js
> node scripts/postinstall || echo "ignore"

Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library!

The project needs your help! Please consider supporting of core-js on Open Collective or Patreon:
> https://opencollective.com/core-js
> https://www.patreon.com/zloirock

Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -)

> uglifyjs-webpack-plugin@0.4.6 postinstall D:\vue\vue-test\node_modules\webpack\node_modules\uglifyjs-webpack-plugin
> node lib/post_install.js

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN ajv-keywords@3.4.1 requires a peer of ajv@^6.9.1 but none is installed. You must install peer dependencies yourself.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.9 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.9: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

added 1208 packages from 669 contributors and audited 11766 packages in 196.113s
found 10 vulnerabilities (6 moderate, 4 high)
run `npm audit fix` to fix them, or `npm audit` for details

# Project initialization finished!
# ========================

To get started:

cd vue-test
npm run dev

Documentation can be found at https://vuejs-templates.github.io/webpack

tips:
npm install -g npm (升级npm至最新版本)
npm cache clean --force (出现报错可清除缓存)

启动项目

1
2
3
4
5
6
7
8
9
10
$ cd vue-test
$ npm run dev

> vue-test@1.0.0 dev D:\vue\vue-test
> webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

13% building modules 26/33 modules 7 active ...ue-test\src\components\HelloWorld.vue{ parser: "babylon" } is deprecated; we now treat it as { parser: "babel" }.
95% emitting DONE Compiled successfully in 11954ms14:06:01

I Your application is running here: http://localhost:8080

vue 项目目录解析

vue

  • build:构建脚本目录

  • config:项目配置目录

  • node_modules:npm 加载的项目依赖目录

  • src:开发目录,基本上要做的事情都集中在这个目录,里面包含几个目录和文件:

    • assets:资源目录,放置一些图片或者公共 js、公共 css,这里的资源会被 webpack 构建

    • components:组件目录,我们写的组件就放在这个目录里面

    • router:前端路由,我们需要配置的路由路径写在 index.js 里面

    • App.vue:根组件

    • main.js:入口 js 文件

  • static:静态资源目录,如图片、字体等,不会被 webpack 构建

  • index.html:首页入口文件,可以添加一些 meta 信息等

  • package.json:npm 包配置文件,定义了项目的 npm 脚本,依赖包等信息

开发 Frist.vue 项目

  • components 目录下新建一个 views 目录,并新建组件 First.vue
  • router 目录下的 index.js 配置路由路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import First from '@/components/views/First'

Vue.use(Router)

export default new Router({

routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},{
path: '/first',
name: 'First',
component: First
}
]
})
  • First.vue 文件 template 写 html,script 写 js,style 写 css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div class="first-app">
{{msg}}
</div>
</template>

<script>
export default {
name: "First",
data() {
return {
msg: "Welcome to FirstApp"
};
}
};
</script>

<style>
</style>
  • http://localhost:8080/#/first,查看页面效果

SSH

发表于 2019-07-08 | 更新于 2019-12-03 | 分类于 Linux

SSH 协议

SSH

SSH(Secure Shell Protocol,安全外壳协议),是建立在应用层和传输层基础上的 一种加密的网络安全传输协议。

img

OpenSSH

OpenSSH:是基于 SSH 协议实现使用最广泛的 免费开源软件。

优点:

  • 安全可靠
  • 便捷

OpenSSH 套件工具:

ssh:远程登录

1
2
3
4
5
6
7
8
9
语法:ssh [-l login_name] [-p port] [user@host]

示例:
ssh 192.168.0.11 # 不指定用户,默认使用当前宿主用户的用户名登录
ssh root@192.168.0.11 # 指定用户登录
ssh root@192.168.0.11 -p 2222 # 指定端口,默认端口22
ssh root@192.168.0.11 "ls /usr/local" # 远程登录后执行某命令

备注:配置文件/etc/ssh/sshd_config,修改ssh登录端口和禁止root登录,可以防止被端口扫描

sshd:服务端进程服务

1
2
服务端修改文件配置:vim /etc/ssh/sshd_config 
配置完成之后要重启服务:systemctl restart sshd.service

scp:Secure Copy,远程安全拷贝文件和目录(加密)

1
2
3
4
5
6
7
语法:scp [-P port] [file|folder] [user@host]:[remote_folder]

示例:
scp mysql.sh user@host:/tmp # 本地文件拷贝到远程目录
scp -r mysqldata user@host:/tmp # 本地目录拷贝到远程目录
scp root@host:/tmp file # 文件下载
scp -P 10022 /usr/local/src/mysql-5.7.23-el7-x86_64.tar.gz root@10.200.62.4:/tmp

sftp:Secure File Transfer Protocol,安全文件传输命令行工具,使用方式和 ftp 类似,但它使用 SSH 作为底层传输协议,安全性比 ftp 好很多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
语法:sftp -oPort=<port> <user>@<host>

常用命令:
help/?:打印帮助信息。
pwd:查看远程服务器当前目录
cd <dir>:将远程服务器的当前目录更改为<dir>
ls:显示远程服务器上当前目录的文件名
ls -l:显示远程服务器上当前目录的文件详细列表
get <file>:下载指定文件 <file>
put <file>:上传指定文件<file>

示例:
[iteblog@www.iteblog.com ~]$ sftp -oPort=22 iteblog@sftp.iteblog.com
Connecting to sftp.iteblog.com...
iteblog@sftp.iteblog.com's password:
sftp> ls /
/iteblog.txt
sftp> ls -l /iteblog.txt
-rw-r--r-- 2 50049 50049 4096 Jun 21 03:23 /iteblog.txt
sftp>

也可以使用 FileZilla 连接 SFTP 服务器:主机 IP 地址、用户名、密码、端口,端口默认为 22。

img

ssh-keygen:生成密钥的工具

  • -t:指定生成密钥类型(rsa、dsa 等)
  • -P:指定 密语,用于确保私钥的安全
  • -f:指定存放密钥的文件(公钥文件默认和私钥同目录下,不同的是存放公钥的文件名需要加上后缀 .pub)
  • -C 用来添加注释

~/.ssh 目录下有四个文件:

  • id_rsa:私钥文件
  • id_rsa.pub:公钥文件
  • authorized_keys:保存已授权的客户端公钥
  • known_hosts:保存已认证的远程主机 ID

img

需要注意的是:一台主机可能既是 Client,也是 Server。所以会同时拥有 authorized_keys 和 known_hosts。

SSH 工作原理

对称加密与非对称加密

对称加密

含义:加密与解密使用同一套秘钥。

问题:考虑到数量庞大的 Client 端,很难保证密钥不被泄露,如何安全的保存密钥 ?

img

img

非对称加密

含义:加密与解决密码不同,存在两个密钥,“公钥” 和 “私钥”。

两个密钥的特性:公钥加密后的密文,只能通过对应的私钥进行解密,而通过公钥推理出私钥的可能性微乎其微。

img

1
2
3
4
5
远程 Server 收到 Client 端用户 TopGun 的登录请求,Server 把自己的公钥发给用户。
Client 使用这个公钥,将密码进行加密。
Client 将加密的密码发送给 Server端。
远程 Server 用自己的私钥,解密登录密码,然后验证其合法性。
若验证结果,给 Client 相应的响应。

图解公钥与私钥

公钥:可以通过网络传输,别人可以随意截获的密钥。

私钥:不能通过网络进行传输,也防止别人截获的密钥。

交互过程:

(1)鲍勃有两把钥匙,一把是公钥,另一把是私钥。

PubKey1

(2)鲍勃把公钥送给他的朋友们 – 帕蒂、道格、苏珊每人一把

PubKey2

(3)苏珊要给鲍勃写一封保密的信,她写完后用鲍勃的公钥加密,就可以达到保密的效果。

PubKey3

(4)鲍勃收信后,用私钥解密,就看到了信件内容。这里要强调的是,只要鲍勃的私钥不泄露,这封信就是安全的,即使落在别人手里,也无法解密。

PubKey4

(5)鲍勃给苏珊回信,决定采用”数字签名”。他写完后先用 Hash 函数,生成信件的摘要(digest)。

PubKey5

(6)然后,鲍勃使用私钥,对这个摘要加密,生成”数字签名”(signature)。

PubKey6

(7)鲍勃将这个签名,附在信件下面,一起发给苏珊。

PubKey7

(8)苏珊收信后,取下数字签名,用鲍勃的公钥解密,得到信件的摘要。由此证明,这封信确实是鲍勃发出的。

PubKey8

(9)苏珊再对信件本身使用 Hash 函数,将得到的结果,与上一步得到的摘要进行对比。如果两者一致,就证明这封信未被修改过。

PubKey9

(10)复杂的情况出现了,道格想欺骗苏珊,他偷偷使用了苏珊的电脑,用自己的公钥换走了鲍勃的公钥。此时,苏珊实际拥有的是道格的公钥,但是还以为这是鲍勃的公钥。因此,道格就可以冒充鲍勃,用自己的私钥做成”数字签名”,写信给苏珊,让苏珊用假的鲍勃公钥进行解密。

PubKey10

(11)后来,苏珊感觉不对劲,发现自己无法确定公钥是否真的属于鲍勃。她想到了一个办法,要求鲍勃去找”证书中心”(Certificate Authority,简称 CA),为公钥做认证。证书中心用自己的私钥,对鲍勃的公钥和一些相关信息一起加密,生成”数字证书”(Digital Certificate)。

PubKey11

(12)鲍勃拿到数字证书以后,就可以放心了。以后再给苏珊写信,只要在签名的同时,再附上数字证书就行了。

PubKey12

(13)苏珊收信后,用 CA 的公钥解开数字证书,就可以拿到鲍勃真实的公钥了,然后就能证明”数字签名”是否真的是鲍勃签的。

PubKey13

两种安全验证方式

基于口令的安全验证(用户名/密码)

  • 客户端发送登录请求 ssh user@host;
  • 服务器接受请求,将服务器的公钥 id_rsa.pub 发送给客户端;
  • 客户端输入密码,密码使用 id_rsa.pub 加密后发送给服务器(敏感信息安全传输);
  • 服务器接受加密后的密码,使用服务器私钥 id_rsa 解密,匹配认证密码是否合法(如果合法!登录成功);
  • 客户端生成会话数据加密 sess_key,使用 id_rsa.pub 加密后传输给服务器(会话密钥);
  • 服务器获取到后使用 id_rsa 解密,得到 sess_key;
  • 客户端和服务器通过 sess_key 进行会话数据安全传输。

基于密钥的安全验证

简单地说,就是客户端自己生成公钥私钥(通常采用 ssh-keygen 程序生成),然后将公钥以某种方式(通常是手动添加)保存到服务器 ~/.ssh/authorized_keys 文件中,以后服务器都会接受客户端传过来的经过会话密钥加密过的公钥,然后解密得到公钥之后和本地 authorized_keys 配置的公钥是否相等,如果是则允许登陆。

小结

  • SSH 是安全的加密协议,用于远程连接 Linux 服务器;
  • SSH 的默认端口是 22,安全协议版本是 SSH2;
  • SSH 服务器端主要包含2个服务功能 SSH 连接和 SFTP 服务器;
  • SSH 客户端包含 ssh 连接命令和远程拷贝 scp 命令等。

服务器初始化

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
# /bin/bash

if [ $(id -u) != "0" ]; then
errorLog "错误:请用root账户运行此脚本"
exit 1
fi
echo "提升权限..."
if [[ ! `cat /etc/sudoers | grep -v grep | grep haieradmin` ]] ; then
echo "需要提升权限。。。"
sed -i '/## Allow root to run any commands anywhere / a\haieradmin ALL=(ALL) NOPASSWD:ALL' /etc/sudoers
if [[ ! `cat /etc/sudoers | grep -v grep | grep haieradmin` ]] ; then
echo "权限提升失败..."
else
echo "权限提升成功..."
fi
else
echo "haieradmin已经是sudoers"
fi

echo "开启22端口访问..."
firewall-cmd --permanent --zone=public --add-port=22/tcp
firewall-cmd --reload

echo "删除hosts.deny..."
sed -i 's/sshd:all/ /g' /etc/hosts.deny

echo "追加hosts.allow..."
if [[ `cat /etc/hosts.allow | grep -v 10.138.*.*` ]]; then
echo "追加10.138.*.*"
echo "sshd:10.138.*.*" >> /etc/hosts.allow
fi

FAQ

问题:CentOS 7.3 配置 SSH 免密码登录后仍要输入密码的解决方法?

原因分析:

1
2
# tail /var/log/secure -n 20
Authentication refused: bad ownership or modes for directory /home/haieradmin

sshd 为了安全,对属主的目录和文件权限有所要求,如果权限不对,则ssh的免密码登陆不生效。

  • .ssh 目录权限为 700
  • rsa_id.pub 及 authorized_keys 权限一般为 644
  • rsa_id 权限必须为 600

解决方法:检测目录权限,把不符合要求的按要求设置权限即可。

MySQL · SQL

发表于 2019-07-05 | 更新于 2019-12-19 | 分类于 MySQL

连接

1
mysql -h <host> -P <port> -u <user> -p <password>

库

1
2
3
4
5
6
7
8
9
10
11
12
# 查看库
show databases;
show create database 'dbname'

# 创建数据库
create database 'dbname' /*!40100 DEFAULT CHARACTER SET utf8 */

# 删除数据库
drop database 'dbname'

# 查看当前时间、用户名、数据库版本
select now(), user(), version();

表

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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# 创建表
CREATE [TEMPORARY] TABLE[ IF NOT EXISTS] [库名.]表名 ( 表的结构定义 )[ 表选项] 每个字段必须有数据类型,最后一个字段后不能有逗号,TEMPORARY 临时表,会话结束时表自动消失

字段名 数据类型 [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string']

-- 字符集
CHARSET = charset_name,如果表没有设定,则使用数据库字符集

-- 存储引擎
ENGINE = engine_name
表在管理数据时采用的不同的数据结构,结构不同会导致处理方式、提供的特性操作等不同
常见的引擎:InnoDB MyISAM Memory/Heap BDB Merge Example CSV MaxDB Archive
不同的引擎在保存表的结构和数据时采用不同的方式
MyISAM表文件含义:.frm表定义,.MYD表数据,.MYI表索引
InnoDB表文件含义:.frm表定义,表空间数据和日志文件
SHOW ENGINES -- 显示存储引擎的状态信息
SHOW ENGINE 引擎名 {LOGS|STATUS} -- 显示存储引擎的日志或状态信息

-- 自增起始数
AUTO_INCREMENT = 行数

-- 数据文件目录
DATA DIRECTORY = '目录'

-- 索引文件目录
INDEX DIRECTORY = '目录'

-- 表注释
COMMENT = 'string'

-- 分区选项
PARTITION BY ... (详细见手册)

# 修改表
-- 修改表本身的选项
ALTER TABLE 表名 表的选项
eg: ALTER TABLE 表名 ENGINE=MYISAM;

-- 对表进行重命名
RENAME TABLE 原表名 TO 新表名
RENAME TABLE 原表名 TO 库名.表名 (可将表移动到另一个数据库)

-- 修改表的字段机构(13.1.2. ALTER TABLE语法)
ALTER TABLE 表名 操作名

-- 操作名
ADD[ COLUMN] 字段定义 -- 增加字段
AFTER 字段名 -- 表示增加在该字段名后面
FIRST -- 表示增加在第一个
ADD PRIMARY KEY(字段名) -- 创建主键
ADD UNIQUE [索引名] (字段名)-- 创建唯一索引
ADD INDEX [索引名] (字段名) -- 创建普通索引
DROP[ COLUMN] 字段名 -- 删除字段
MODIFY[ COLUMN] 字段名 字段属性 -- 支持对字段属性进行修改,不能修改字段名(所有原有属性也需写上)
CHANGE[ COLUMN] 原字段名 新字段名 字段属性 -- 支持对字段名修改
DROP PRIMARY KEY -- 删除主键(删除主键前需删除其AUTO_INCREMENT属性)
DROP INDEX 索引名 -- 删除索引
DROP FOREIGN KEY 外键 -- 删除外键

eg.
CREATE TABLE `testdemo` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` char(20) NOT NULL DEFAULT '',
`address` varchar(50),
`age` tinyint unsigned NOT NULL DEFAULT 0,
`gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
);

# 查看表结构
desc test;
show create table test\G
show table status from 'db_name';

# 复制表
CREATE TABLE 'newname' LIKE 'oldname';
INSERT INTO 'newname' SELECT * FROM 'oldname';

# 修改表存储引擎
ALTER TABLE 'table_name' engine=myisam;

# 删除表
DROP TABLE[ IF EXISTS] 表名

# 清空表数据,truncate 是删除表再创建,delete 是逐条删除
TRUNCATE [TABLE] 表名

# 复制表结构
CREATE TABLE 表名 LIKE 要复制的表名

# 复制旧表的数据到新表(假设两个表结构一样)
INSERT INTO 新表 SELECT * FROM 旧表

# 复制旧表的数据到新表(假设两个表结构不一样)
INSERT INTO 新表(字段1,字段2,……) SELECT 字段1,字段2,…… FROM 旧表

# 复制表结构和数据
CREATE TABLE 表名 [AS] SELECT * FROM 要复制的表名

# CRUD
-- 增
INSERT [INTO] 表名 [(字段列表)] VALUES (值列表)[, (值列表), ...]
INSERT [INTO] 表名 SET 字段名=值[, 字段名=值, ...]

-- 查
SELECT 字段列表 FROM 表名[ 其他子句]

-- 删
DELETE FROM 表名[ 删除条件子句]

-- 改
UPDATE 表名 SET 字段名=新值[, 字段名=新值] [更新条件]

索引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 删除索引
DROP index idx_name on 'table_name'

# 添加自增主键
ALTER TABLE 'table_name' ADD id bigint(10) PRIMARY KEY AUTO_INCREMENT;

# 查看表索引
SHOW INDEX FROM 'table_name';

# 添加主键
ALTER TABLE 'table_name' ADD PRIMARY KEY (column)

# 创建唯一索引
ALTER TABLE 'table_name' ADD UNIQUE (column)

# 创建普通索引
ALTER TABLE 'table_name' ADD 'index_name'(column)

# 创建聚合索引
ALTER TABLE 'table_name' ADD INDEX 'index_name' (column1, column2, column3)

视图

1
2
3
4
5
6
7
8
# 查询视图
SELECT * FROM information_schema.views;

# 创建视图
create view 'viewname' as 'sql'

# 删除视图
drop view 'viewname'

复杂查询

DISTINCT

去除重复记录,默认为 ALL 选项

LIKE

1
select * from 'table' where field like '%value%'

UNION & UNION ALL

1
2
3
4
5
6
7
8
9
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2

SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2

注意:默认地,UNION 操作符选取不同的值,如果允许重复的值,请使用 UNION ALL。

子查询

1
select a,b,c from a where d IN (select d from b )

BETWEEN AND

1
select * from table1 where time between time1 and time2

IN

1
select * from table1 where a [not] in (‘值1’,’值2’,’值4’,’值6’)

ORDER BY

语法:

1
2
SELECT field1, field2,...fieldN FROM table_name1, table_name2...
ORDER BY field1, [field2...] [ASC [DESC]]
  • 你可以使用 ASC 或 DESC 关键字来设置查询结果是按升序或降序排列,默认情况下,按升序排列。
  • 你可以添加 WHERE…LIKE 子句来设置条件。
1
select * from 'tabname' order by field1,field2 [desc]

统计信息

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
57
58
59
60
61
62
63
64
65
66
# 查询数据库总量
select concat(round(sum((data_length + index_length)/1024/1024/1024),2),'GB') as data from information_schema.tables;

# 查询所有库数据量并排序
SELECT table_schema, CONCAT(
TRUNCATE(SUM(data_length)/1024/1024,2),'MB') AS data_size, CONCAT(
TRUNCATE(SUM(index_length)/1024/1024,2),'MB') AS index_size
FROM information_schema.tables
GROUP BY table_schema
ORDER BY SUM(data_length) DESC;
+--------------------+------------+------------+
| table_schema | data_size | index_size |
+--------------------+------------+------------+
| csomo-barcode | 51872.64MB | 49203.56MB |
| cosmodb | 30257.57MB | 13855.68MB |
| cosmo_im_1001 | 19769.54MB | 6251.67MB |
| cosmoimbase | 17594.54MB | 18239.81MB |
| cosmo_im_1004 | 3141.99MB | 4099.13MB |
| cosmo_im_1012 | 1524.87MB | 1592.03MB |
| cosmo_im_1010 | 1464.20MB | 2176.00MB |
| cosmo_im_1016 | 1092.29MB | 1543.65MB |
| cosmo_im_1009 | 793.96MB | 1612.11MB |
| cosmo_im_1003 | 662.42MB | 1417.97MB |
| cosmo_im_1006 | 200.44MB | 288.24MB |
| cosmo_im_1047 | 184.14MB | 90.46MB |
| cosmo_im_1038 | 32.15MB | 46.03MB |
| mysql | 22.60MB | 0.14MB |
| test | 7.06MB | 0.03MB |
| information_schema | 0.00MB | 0.00MB |
| performance_schema | 0.00MB | 0.00MB |
+--------------------+------------+------------+

# 查询单个表数据量
select table_name,table_rows,CONCAT(
TRUNCATE(SUM(data_length)/1024/1024,2),'MB') AS data_size, CONCAT(
TRUNCATE(SUM(index_length)/1024/1024,2),'MB') AS index_size from information_schema.tables where TABLE_SCHEMA = 'mqm' and table_name='t_batch';

# 查询单个库中表数据排序
select table_name,table_rows from information_schema.tables where TABLE_SCHEMA= 'employees' order by table_rows desc;
+----------------------+------------+
| table_name | table_rows |
+----------------------+------------+
| salaries | 2838426 |
| titles | 441772 |
| dept_emp | 331570 |
| employees | 299600 |
| dept_manager | 24 |
| departments | 9 |
| current_dept_emp | NULL |
| dept_emp_latest_date | NULL |
+----------------------+------------+

# 查询单个库中表排序
SELECT CONCAT(table_schema,'.',table_name) AS 'Table Name', table_rows AS 'Rows', CONCAT(ROUND(data_length/(1024*1024),2),'M') AS 'Data Size',CONCAT(ROUND(index_length/(1024*1024),2),'M') AS 'Index Size', CONCAT(ROUND((data_length+index_length)/(1024*1024),2),'M') AS'Total'FROM information_schema.TABLES WHERE TABLE_SCHEMA= 'employees' ORDER BY --total DESC;
+--------------------------------+---------+-----------+------------+--------+
| Table Name | Rows | Data Size | Index Size | Total |
+--------------------------------+---------+-----------+------------+--------+
| employees.salaries | 2838426 | 95.63M | 0.00M | 95.63M |
| employees.titles | 441772 | 19.56M | 0.00M | 19.56M |
| employees.dept_emp | 331570 | 11.52M | 5.52M | 17.03M |
| employees.employees | 299600 | 14.52M | 0.00M | 14.52M |
| employees.dept_manager | 24 | 0.02M | 0.02M | 0.03M |
| employees.departments | 9 | 0.02M | 0.02M | 0.03M |
| employees.current_dept_emp | NULL | NULL | NULL | NULL |
| employees.dept_emp_latest_date | NULL | NULL | NULL | NULL |
+--------------------------------+---------+-----------+------------+--------+

复制

1
2
3
4
5
6
7
8
9
10
11
12
13
# 取消复制
stop slave;
reset slave all;

# 建立复制
CHANGE MASTER TO
MASTER_HOST='10.133.7.18',
MASTER_USER='repl',
MASTER_PASSWORD='Changeme_123',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-binlog.000297',
MASTER_LOG_POS=900834433,
MASTER_CONNECT_RETRY=10;

Percona Toolkit · 简介安装

发表于 2019-07-05 | 更新于 2019-11-15 | 分类于 MySQL

简介

Percona Toolkit 简称 pt,专用于 MySQL 运维管理的工具箱,几乎能满足 MySQL 日常运维的所有需求,使用 Perl 编写。

安装

① 安装

1
2
3
4
5
6
7
8
9
10
11
$ wget http://devops-files.oss-cn-qingdao.aliyuncs.com/percona-toolkit-3.0.13-el7-x86_64-bundle.tar
$ tar xvf percona-toolkit-3.0.13-el7-x86_64-bundle.tar
$ rpm -ivh percona-toolkit-3.0.13-1.el7.x86_64.rpm

warning: percona-toolkit-3.0.13-1.el7.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID 8507efa5: NOKEY
error: Failed dependencies:
perl(DBD::mysql) >= 1.0 is needed by percona-toolkit-3.0.13-1.el7.x86_64
perl(IO::Socket::SSL) is needed by percona-toolkit-3.0.13-1.el7.x86_64
perl(Digest::MD5) is needed by percona-toolkit-3.0.13-1.el7.x86_64
perl(Time::HiRes) is needed by percona-toolkit-3.0.13-1.el7.x86_64
perl(Term::ReadKey) is needed by percona-toolkit-3.0.13-1.el7.x86_64

② 解决依赖

1
2
3
4
5
6
7
8
9
$ yum -y install perl-DBD-MySQL
$ yum -y install perl-Digest-MD5
$ yum -y install perl-IO-Socket-SSL
$ yum -y install perl-TermReadKey
$ yum -y install perl-Time-HiRes
$ rpm -ivh percona-toolkit-3.0.13-1.el7.x86_64.rpm

$ pt-archiver --help
Usage: pt-archiver [OPTIONS] --source DSN --where WHERE

工具

命令 作用
pt-align 对齐其他工具的输出
pt-archiver 将表数据归档到另一个表或文件中
pt-config-diff 比较配置文件和参数
pt-deadlock-logger 提取和记录 mysql 死锁信息
pt-diskstats 查看系统磁盘状态
pt-duplicate-key-checker 列出并删除重复的索引和外键
pt-fifo-split 模拟切割文件并输出
pt-find 查找表并执行命令
pt-fingerprint 将查询转成密文
pt-fk-error-logger 提取和记录外键信息
pt-heartbeat 监控复制延迟
pt-index-usage 分析日志中索引使用情况,并出报告
pt-ioprofile 查询进程 IO 并打印活动表
pt-kill kill 掉符合条件的 sql
pt-mext 并行查看 status 样本信息
pt-mysql-summary 对 mysql 配置和 status 进行汇总
pt-online-schema-change 在线修改表结构
pt-pmp 为查询结果跟踪,并汇总跟踪结果
pt-query-digest 分析查询日志,并产生报告
pt-secure-collect 收集、打包、加密数据
pt-show-grants 规范化和打印权限
pt-sift 浏览由 pt-stalk 创建的文件
pt-slave-delay 设定从落后主的时间
pt-slave-find 查找和打印所有复制层级关系
pt-slave-restart 监控 salve 错误,并尝试重启 salve
pt-stalk 出现问题时,收集诊断数据
pt-summary 收集和显示系统概况
pt-table-checksum 校验主从复制一致性
pt-table-sync 高效同步表数据
pt-table-usage 分析日志中查询并分析表使用情况
pt-upgrade 在多个服务器上执行查询,并比较不同
pt-variable-advisor 分析参数,并提出建议
pt-visual-explain 格式化执行计划

MySQL · 配置参数 · innodb_buffer_pool_size

发表于 2019-06-18 | 更新于 2019-10-20 | 分类于 MySQL

简介

缓存是计算机系统非常重要的组成部分,因为访问硬盘相比缓存可能会慢 100 到 100000 倍,取决于访问的数据量。MySQL 作为一个存储系统,同样具有缓冲池(Buffer Pool)机制,以避免每次查询数据都进行磁盘 IO,不同存储引擎缓存方式有所区别:

  • MyISAM 使用的是操作系统的文件系统缓存,来缓存那些经常被查询的数据。

  • InnoDB 不依赖操作系统的缓存,自己在 InnoDB Buffer Pool 处理缓存。

① InnoDB Buffer Pool 主要作用?

缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘 IO,起到加速访问的作用。

② 为什么不把所有数据都放到缓冲池里?

凡事都具备两面性,抛开数据易失性不说,访问快速的反面是存储容量小:

  • 缓存访问快,但容量小,数据库存储了 200G 数据,缓存容量可能只有 64G;
  • 内存访问快,但容量小,买一台笔记本磁盘有 2T,内存可能只有 16G;

因此,只能把“最热”的数据放到“最近”的地方,以“最大限度” 的降低磁盘访问。

③ 如何管理与淘汰缓冲池,使得性能最大化呢?

参数说明

参数:innodb_buffer_pool_size

介绍:配置缓冲池的大小,在内存允许的情况下,DBA 往往会建议调大这个参数,越多数据和索引放到内存里,数据库的性能会越好。

参数:innodb_old_blocks_pct

介绍:老生代占整个 LRU 链长度的比例,默认是 37,即整个 LRU 中新生代与老生代长度比例是 63:37。

参数:innodb_old_blocks_time

介绍:老生代停留时间窗口,单位是毫秒,默认是 1000,即同时满足“被访问”与“在老生代停留时间超过 1 秒两个条件,才会被插入到新生代头部。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> select @@innodb_buffer_pool_size/1024/1024;
+----------------------------------- --+
| @@innodb_buffer_pool_size/1024/1024 |
+-------------------------------------+
| 1024.00000000 |
+-------------------------------------+
1 row in set (0.00 sec)

mysql> show variables like 'innodb_old%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| innodb_old_blocks_pct | 37 |
| innodb_old_blocks_time | 1000 |
+------------------------+-------+
2 rows in set (0.01 sec)

InnoDB Buffer Pool 缓存命中率计算:

1
2
脏页率计算公式:innodb_buffer_pool_pages_dirty / innodb_buffer_pool_pages_data * 100%
使用率计算公式:innodb_buffer_pool_pages_data / ( innodb_buffer_pool_pages_data + innodb_buffer_pool_pages_free ) * 100%

将缓冲池划分为多个单独的实例,通过减少不同线程读取和写入缓存的争用来提高并发性。Buffer Pool 可以存放多个 Instance,每个 Instance 由多个 Chunk 组成。Instance 的数量范围和 Chunk 的总数量范围分别为 1-64,1-1000。

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 默认值
innodb_buffer_pool_size 默认值为128M
innodb_buffer_pool_instances 默认值为1
innodb_buffer_pool_chunk_size 默认值为128M

# 计算公式
innodb_buffer_pool_size = innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances * N

# 总缓存大小
select @@innodb_buffer_pool_size/1024/1024;

# 缓存池数量
select @@innodb_buffer_pool_instances;

# 每个缓存池的大小
select @@innodb_buffer_pool_chunk_size/1024/1024;

Tips:当设置的 Buffer Pool 不等于 Chunk * Instance 倍数时,MySQL 会自动调整 Buffer Pool 的大小 ( 向上取值到最近的一次倍数 )。

小结:

  • 缓冲池(buffer pool)是一种常见的降低磁盘访问的机制

  • 缓冲池通常以页(page)为单位缓存数据

  • 缓冲池的常见管理算法是 LRU,memcache,OS,InnoDB 都使用了这种算法

  • InnoDB 对普通 LRU 进行了优化:(1)将缓冲池分为老生代和新生代,入缓冲池的页,优先进入老生代,页被访问才进入新生代,以解决预读失效的问题;(2)页被访问,且在老生代停留时间超过配置阈值的,才进入新生代,以解决批量数据访问,大量热数据淘汰的问题。

设置 InnoDB Buffer Pool

InnoDB Buffer Pool 缓存了表数据和二级索引在内存中,设置 innodb_buffer_pool_size 合理数值对实例性能影响很大。

  • 设置偏小,会导致数据库大量直接对磁盘的访问,查询效率低。
  • 设置过大,会导致数据库进程占用内存太多,发生 OOM。

独立服务器

如果仅 MySQL 服务独享服务器资源,推荐设置 innodb_buffer_pool_size 为服务器总可用内存的 80%,具体设置多少,需要根据服务器内存大小和消耗进行调整。

设置 80% 的原因,是因为其它也需要内存:

  • 单次查询至少需要几K(甚至几M)的内存
  • 其他各种内部的 MySQL 结构和缓存
  • 有一些 MySQL 文件是在 OS 缓存里(binary 日志,relay 日志,事务日志等)
  • 操作系统消耗内存

修改方法

  • MySQL 5.7 版本之后,可以在线修改
1
2
3
4
5
6
7
set global innodb_buffer_pool_size = size_in_bytes;
select @@innodb_buffer_pool_size/1024/1024;
+-------------------------------------+
| @@innodb_buffer_pool_size/1024/1024 |
+-------------------------------------+
| 128.00000000 |
+-------------------------------------+
1
2
3
Tips:
① innodb_buffer_pool_size 在线修改时,用户的请求将会阻塞,需要在业务低峰期和没有大事务操作时候进行
② 同时要修改配置文件 my.cnf,防止重启后恢复到原来的值
  • MySQL 5.7 版本之前,需要修改 my.cnf 配置文件,然后重启 MySQL 服务
1
2
[mysqld]
innodb_buffer_pool_size = 20480M

参考

数据库内核月报

INNODB_BUFFER_POOL_SIZE:设置最佳内存值

1…161718
Hui Rao

Hui Rao

最好的成长是分享
173 日志
19 分类
14 标签
GitHub E-Mail
© 2021 Hui Rao
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Gemini v7.1.0
|