0%

1、概述

1.1、目的

1.2、环境信息

  • 操作系统版本CentOS Linux release 7.2.1511 (Core)
  • MariaDB:10.1.14-MariaDB MariaDB Server
  • 物理机1:node1:10.10.90.167
  • 物理机2:node2:10.10.90.174
  • 物理机3:node3:10.10.90.181

2、Galera集群搭建步骤

2.1、MariaDB安装步骤

MariaDB参数

MariaDB-10.1.14安装步骤与MySQL-5.6一致,只是一些在MySQL中的参数,在MarIaDB中不能使用或者被忽略。在QData的参数模板中,以下参数会导致数据库初始化话失败

1
2
3
4
5
6
gtid-mode=on # GTID only
enforce-gtid-consistency=true # GTID only
slave_parallel_type=LOGICAL_CLOCK
innodb_undo_log_truncate=ON
log_timestamps=SYSTEM
slave_preserve_commit_order=ON

以下参数会使数据库初始化的过程中出现警告:

1
2
3
4
5
6
slave_pending_jobs_size_max=128M
table_open_cache = 4096
binlog-rows-query-log-events
master-info-repository
relay-log-info-repository
slave-parallel-workers

使用的参数模板如下:

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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
[client]
loose_default-character-set = utf8
port=3306
socket=/home/mysql/data/mysqldata1/sock/mysql.sock
user=admin

[mysqldump]
quick
max_allowed_packet = 2G
default-character-set = utf8

[mysql]
no-auto-rehash
show-warnings
prompt="\\u@\\h : \\d \\r:\\m:\\s> "
default-character-set = utf8

[myisamchk]
key_buffer = 512M
sort_buffer_size = 512M
read_buffer = 8M
write_buffer = 8M

[mysqlhotcopy]
interactive-timeout

[mysqld_safe]
user=mysql
open-files-limit = 65535

[mysqld]
#large-pages
#***********************************common parameters******************************
read_only=on
#memlock
default-storage-engine = INNODB
character-set-server=utf8
collation_server = utf8_bin

user=mysql
port=3306
socket=/home/mysql/data/mysqldata1/sock/mysql.sock
pid-file=/home/mysql/data/mysqldata1/sock/mysql.pid
datadir=/home/mysql/data/mysqldata1/mydata
tmpdir=/home/mysql/data/mysqldata1/tmpdir

skip-name-resolve
skip_external_locking

lower_case_table_names=1
event_scheduler=0
back_log=512
default-time-zone='+8:00'

max_connections = 3000
max_connect_errors=99999
max_allowed_packet = 64M
#slave_pending_jobs_size_max=128M
max_heap_table_size = 8M
max_length_for_sort_data = 16k

wait_timeout=172800
interactive_timeout=172800

net_buffer_length = 8K
read_buffer_size = 2M
read_rnd_buffer_size = 2M
sort_buffer_size = 2M
join_buffer_size = 4M
binlog_cache_size = 2M

#table_open_cache = 4096
table_open_cache_instances = 2
table_definition_cache = 4096
thread_cache_size = 512
tmp_table_size = 8M

query_cache_size=0
query_cache_type=OFF
explicit_defaults_for_timestamp=ON

#******************************* Logs related settings ***************************
log-error=/home/mysql/data/mysqldata1/log/error.log
long_query_time = 1
slow_query_log
slow_query_log_file=/home/mysql/data/mysqldata1/slowlog/slow-query.log
log_slow_slave_statements
#log_queries_not_using_indexes

#******************************* Replication related settings **********************

#### For Master
server-id=3306191
log-bin=/home/mysql/data/mysqldata1/binlog/mysql-bin
binlog-format=ROW
binlog-checksum=CRC32
#binlog-rows-query-log-events=1
max_binlog_size = 512M
expire_logs_days=15
sync_binlog=1
master-verify-checksum=1
#master-info-repository=TABLE
auto_increment_increment=2
auto_increment_offset=2

#### For Slave
relay-log=/home/mysql/data/mysqldata1/relaylog/mysql-relay-bin
#relay-log-info-repository=TABLE
relay-log-recovery=1
#slave-skip-errors=1022,1032,1062,1236
slave-sql-verify-checksum=1
log_bin_trust_function_creators=1
log_slave_updates=1
slave-net-timeout=10
skip-slave-start

#******************************* MyISAM Specific options ****************************
key_buffer_size = 8M
bulk_insert_buffer_size = 8M
myisam_sort_buffer_size = 64M
myisam_max_sort_file_size = 10G
myisam_repair_threads = 1
myisam_recover_options=force

# ***************************** INNODB Specific options ****************************
#### Data options
#innodb_data_home_dir = /home/mysql/data/mysqldata1/innodb_ts
innodb_data_file_path = ibdata1:2048M:autoextend
innodb_file_per_table
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_format_check = ON
innodb_strict_mode = 1
innodb_flush_method = O_DIRECT
innodb_checksum_algorithm=crc32
innodb_autoinc_lock_mode=2

#### Buffer Pool options
innodb_buffer_pool_size = 4G
innodb_buffer_pool_instances = 2
innodb_max_dirty_pages_pct = 75
innodb_adaptive_flushing = ON
innodb_flush_neighbors = 0
innodb_lru_scan_depth = 4096
#innodb_change_buffering = inserts
innodb_old_blocks_time = 1000

#### Redo options
innodb_log_group_home_dir = /home/mysql/data/mysqldata1/innodb_log
innodb_log_buffer_size = 64M
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_flush_log_at_trx_commit = 1
innodb_fast_shutdown = 2
innodb_support_xa = ON

#### Transaction options
innodb_thread_concurrency = 64
innodb_lock_wait_timeout = 120
innodb_rollback_on_timeout = 1
transaction_isolation = READ-COMMITTED

#### IO options
innodb_read_io_threads = 8
innodb_write_io_threads = 16
innodb_io_capacity = 20000
innodb_use_native_aio = 1

#### Undo options
innodb_undo_directory = /home/mysql/data/mysqldata1/undo/
innodb_undo_tablespaces=16
innodb_purge_threads = 4
innodb_purge_batch_size = 512
innodb_max_purge_lag = 65536

#### 5.6/5.7 GTID
#gtid-mode=on # GTID only
#enforce-gtid-consistency=true # GTID only

#### mysql 5.7
#super_read_only=on
secure_file_priv=/data2/
#slave_parallel_workers=16
#slave_parallel_type=LOGICAL_CLOCK
#innodb_undo_log_truncate=ON
#log_timestamps=SYSTEM
#slave_preserve_commit_order=ON

#### mariadb
gtid_strict_mode=on
gtid_domain_id=191

#### galera
wsrep_on=on
wsrep_provider=/usr/local/mysql/lib/galera/libgalera_smm.so
wsrep_provider_options="gcache.size=1G"

wsrep_cluster_name=wqglr_0001
wsrep_cluster_address=gcomm://10.10.90.167:4567,10.10.90.174:4567,10.10.90.181:4567
wsrep_node_name = node3
wsrep_node_address=10.10.90.181:4567
#
#wsrep_sst_method=xtrabackup-v2
#wsrep_sst_auth="xtrabackup:xtrabackuppass"
#wsrep_slave_threads=16
#
#innodb_support_xa = OFF
#sync_binlog=0
#innodb_flush_log_at_trx_commit = 0

安装步骤

  • 创建目录

    1
    2
    3
    mkdir -p /data2/mysqldata1/{binlog,conf,innodb_log,innodb_ts,log,mydata,relaylog,slowlog,sock,tmpdir,undo}
    mkdir -p /home/mysql/{data,program}
    ln -s /data2/mysqldata1 /home/mysql/data/mysqldata1
  • 下载二进制安装包,并上传到对应位置

  • 将安装包解压至指定目录,并建立软链至/usr/local

    1
    2
    tar -zxvf mariadb-10.1.14-linux-x86_64 -c /home/mysql/program/
    ln -s /home/mysql/program/mariadb-10.1.14-linux-x86_64 /usr/local/mysql
  • 添加用户以及用户组

    1
    2
    groupadd mysql
    useradd -r -g mysql mysql
  • 更改目录权限

    1
    chown -R mysql:mysql /data/mysqldata1
  • 填写配置文件
    将上面的配置文件内容写到/etc/my.cnf中

  • 初始化数据库
    1
    2
    cd /usr/local/mysql
    ./scripts/mysql_install_db --defaults-file=/etc/my.cnf --user=mysql

验证安装成功:
查看是否有两个OK

  • 添加service启动方式

    1
    cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
  • 尝试启动数据库,验证数据库正常

    1
    service mysqld start

按照相同的步骤安装三个节点

2.2、Galera集群安装步骤

2.2.1、第一个节点安装

安装步骤:

  • 在配置文件中填写galera集群的配置参数
    一下为最基础的参数配置,一些调优等的配置参数不列在这边

    1
    2
    3
    4
    5
    6
    7
    8
    9
    gtid_strict_mode=on
    gtid_domain_id=191
    wsrep_on=on
    wsrep_provider=/usr/local/mysql/lib/galera/libgalera_smm.so
    wsrep_provider_options="gcache.size=1G"
    wsrep_cluster_name=wqglr_0001
    wsrep_cluster_address=gcomm://10.10.90.167:4567,10.10.90.174:4567,10.10.90.181:4567
    wsrep_node_name = node3
    wsrep_node_address=10.10.90.181:4567
  • 启动第一个节点
    galera集群启动第一个节点的时候需要加上,–wsrep-new-cluster来初始化一个集群,这个只需要在第一个节点第一次启动的时候添加,之后该节点启动时不需要添加该参数,因为这个参数的表示初始化一个新的集群,每次添加该参数,都会初始化一个新的集群

    1
    2
    cd /usr/local/mysql/bin
    ./mysqld_safe --defaults-file=/etc/my.cnf --wsrep-new-cluster &
  • 进入数据库检查,集群状态 show status like ‘%wsrep_%’

    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
    root@localhost : (none) 11:00:08> show status like '%wsrep_%';
    +------------------------------+----------------------------------------------------------------+
    | Variable_name | Value |
    +------------------------------+----------------------------------------------------------------+
    | wsrep_apply_oooe | 0.000000 |
    | wsrep_apply_oool | 0.000000 |
    | wsrep_apply_window | 1.000000 |
    | wsrep_causal_reads | 0 |
    | wsrep_cert_deps_distance | 1.000000 |
    | wsrep_cert_index_size | 1 |
    | wsrep_cert_interval | 0.000000 |
    | wsrep_cluster_conf_id | 10 |
    | wsrep_cluster_size | 3 |
    | wsrep_cluster_state_uuid | 5ace7bde-f5d3-11e7-81fd-b7f62639a9a0 |
    | wsrep_cluster_status | Primary |
    | wsrep_commit_oooe | 0.000000 |
    | wsrep_commit_oool | 0.000000 |
    | wsrep_commit_window | 1.000000 |
    | wsrep_connected | ON |
    | wsrep_evs_delayed | 829f35c1-f5d6-11e7-9525-b21c1d0f3f09:tcp://10.10.90.191:4567:1 |
    | wsrep_evs_evict_list | |
    | wsrep_evs_repl_latency | 0/0/0/0/0 |
    | wsrep_evs_state | OPERATIONAL |
    | wsrep_flow_control_paused | 0.000000 |
    | wsrep_flow_control_paused_ns | 0 |
    | wsrep_flow_control_recv | 0 |
    | wsrep_flow_control_sent | 0 |
    | wsrep_gcomm_uuid | 5acdf3cc-f5d3-11e7-bcb5-46c7c07b299e |
    | wsrep_incoming_addresses | 10.10.90.181:3306,10.10.90.167:3306,10.10.90.174:3306 |
    | wsrep_last_committed | 3 |
    | wsrep_local_bf_aborts | 0 |
    | wsrep_local_cached_downto | 1 |
    | wsrep_local_cert_failures | 0 |
    | wsrep_local_commits | 0 |
    | wsrep_local_index | 1 |
    | wsrep_local_recv_queue | 0 |
    | wsrep_local_recv_queue_avg | 0.074074 |
    | wsrep_local_recv_queue_max | 2 |
    | wsrep_local_recv_queue_min | 0 |
    | wsrep_local_replays | 0 |
    | wsrep_local_send_queue | 0 |
    | wsrep_local_send_queue_avg | 0.000000 |
    | wsrep_local_send_queue_max | 1 |
    | wsrep_local_send_queue_min | 0 |
    | wsrep_local_state | 4 |
    | wsrep_local_state_comment | Synced |
    | wsrep_local_state_uuid | 5ace7bde-f5d3-11e7-81fd-b7f62639a9a0 |
    | wsrep_protocol_version | 7 |
    | wsrep_provider_name | Galera |
    | wsrep_provider_vendor | Codership Oy <info@codership.com> |
    | wsrep_provider_version | 25.3.15(r3578) |
    | wsrep_ready | ON |
    | wsrep_received | 27 |
    | wsrep_received_bytes | 3661 |
    | wsrep_repl_data_bytes | 356 |
    | wsrep_repl_keys | 1 |
    | wsrep_repl_keys_bytes | 31 |
    | wsrep_repl_other_bytes | 0 |
    | wsrep_replicated | 1 |
    | wsrep_replicated_bytes | 451 |
    | wsrep_thread_count | 2 |
    +------------------------------+----------------------------------------------------------------+
    57 rows in set (0.00 sec)

重点关注几个状态:
wsrep_connected=on 表示链接已开启
wsrep_local_index=1 表示集群中的索引值
wsrep_cluster_size=3 表示集群中节点的数量
wsrep_incoming_addresses =0.10.90.181:3306,10.10.90.167:3306,10.10.90.174:3306集群中节点的访问地址

2.2.2、加入一个数据节点

安装步骤

  • 在配置文件中填写galera集群的配置参数
    一下为最基础的参数配置,一些调优等的配置参数不列在这边

    1
    2
    3
    4
    5
    6
    7
    8
    9
    gtid_strict_mode=on
    gtid_domain_id=191
    wsrep_on=on
    wsrep_provider=/usr/local/mysql/lib/galera/libgalera_smm.so
    wsrep_provider_options="gcache.size=1G"
    wsrep_cluster_name=wqglr_0001
    wsrep_cluster_address=gcomm://10.10.90.167:4567,10.10.90.174:4567,10.10.90.181:4567
    wsrep_node_name = node3
    wsrep_node_address=10.10.90.181:4567
  • 启动节点

    1
    service mysqld start
  • 进入数据库检查,集群状态 show status like ‘%wsrep_%’

2.2.3、加入一个仲裁节点

仲裁节点不需要初始化数据库,不需要进行配置,但是数据目录需要创建,数据库程序需要部署

  • 启动仲裁节点

    1
    2
    cd /usr/local/mysql/bin
    ./garbd --address="gcomm://10.10.90.167:4567,10.10.90.174:4567,10.10.90.181:4567" --group=wqglr_0001 --name='10.10.90.181:4567' --log=/home/mysql/data/mysqldata1/log/garbd.log -d
  • 检查仲裁节点加入情况
    node1或者node2上show status like ‘%wsrep_cluster%’;查看集群节点数量,发现集群节点数量增加1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    root@localhost : (none) 01:23:30> show status like '%wsrep_cluster%';
    +--------------------------+--------------------------------------+
    | Variable_name | Value |
    +--------------------------+--------------------------------------+
    | wsrep_cluster_conf_id | 3 |
    | wsrep_cluster_size | 3 |
    | wsrep_cluster_state_uuid | 75b1d970-f681-11e7-a221-af292503fa6e |
    | wsrep_cluster_status | Primary |
    +--------------------------+--------------------------------------+
    4 rows in set (0.00 sec)

2.2.4、验证数据同步

在node1上:

1
2
3
4
create database test1;
use test1;
create table test1(id int primary key auto_increment,name varchar(20));
insert into test1(`name`) values('test1');

在node2上

1
2
3
4
create database test2;
use test2;
create table test1(id int primary key auto_increment,name varchar(20));
insert into test1(`name`) values('test1');

在两个节点上查询数据,发现数据复制正常

2.2.5、脑裂验证

3、安装过程中的问题

galera集群启动过程中,报libssl和libcrypto库缺失

错误日志:

1
2
3
4
5
6
7
8
9
2018-01-09 16:19:28 140122035881856 [Warning] 'table-open-cache-instances' is MySQL 5.6 compatible option. Not used or needed in MariaDB.
2018-01-09 16:19:28 140122035881856 [Note] /usr/local/mysql/bin/mysqld (mysqld 10.1.14-MariaDB) starting as process 31625 ...
2018-01-09 16:19:28 140122035881856 [Note] WSREP: Read nil XID from storage engines, skipping position init
2018-01-09 16:19:28 140122035881856 [Note] WSREP: wsrep_load(): loading provider library '/usr/local/mysql/lib/galera/libgalera_smm.so'
2018-01-09 16:19:28 140122035881856 [ERROR] WSREP: wsrep_load(): dlopen(): libssl.so.6: cannot open shared object file: No such file or directory
2018-01-09 16:19:28 140122035881856 [ERROR] WSREP: wsrep_load(/usr/local/mysql/lib/galera/libgalera_smm.so) failed: Invalid argument (22). Reverting to no provider.
2018-01-09 16:19:28 140122035881856 [Note] WSREP: Read nil XID from storage engines, skipping position init
2018-01-09 16:19:28 140122035881856 [Note] WSREP: wsrep_load(): loading provider library 'none'
2018-01-09 16:19:28 140122035881856 [ERROR] Aborting

解决方案:

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
#ldd libgalera_smm.so
linux-vdso.so.1 => (0x00007ffda1bdc000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fabbb35f000)
librt.so.1 => /lib64/librt.so.1 (0x00007fabbb157000)
libssl.so.6 => not found
libcrypto.so.6 => not found
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fabbae4e000)
libm.so.6 => /lib64/libm.so.6 (0x00007fabbab4b000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fabba935000)
libc.so.6 => /lib64/libc.so.6 (0x00007fabba574000)
/lib64/ld-linux-x86-64.so.2 (0x00007fabbbade000)


[root@node2 /lib64]
#cd /usr/lib64

[root@node2 /usr/lib64]
#ll libssl*
-rwxr-xr-x. 1 root 272536 Nov 20 2015 libssl3.so
lrwxrwxrwx. 1 root 16 Dec 27 15:31 libssl.so -> libssl.so.1.0.1e
lrwxrwxrwx. 1 root 16 Dec 27 15:30 libssl.so.10 -> libssl.so.1.0.1e
-rwxr-xr-x. 1 root 449864 Jun 29 2015 libssl.so.1.0.1e

[root@node2 /usr/lib64]
#ln -s libssl.so.1.0.1e libssl.so.6

[root@node2 /usr/lib64]
#ll libcrypto*
lrwxrwxrwx. 1 root 19 Dec 27 15:31 libcrypto.so -> libcrypto.so.1.0.1e
lrwxrwxrwx. 1 root 19 Dec 27 15:30 libcrypto.so.10 -> libcrypto.so.1.0.1e
-rwxr-xr-x. 1 root 2012880 Jun 29 2015 libcrypto.so.1.0.1e

[root@node2 /usr/lib64]
#ln -s libcrypto.so.1.0.1e libcrypto.so.6


#ldd /usr/local/mysql/lib/galera/libgalera_smm.so
linux-vdso.so.1 => (0x00007ffecdbad000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe44169e000)
librt.so.1 => /lib64/librt.so.1 (0x00007fe441496000)
libssl.so.6 => /lib64/libssl.so.6 (0x00007fe441228000)
libcrypto.so.6 => /lib64/libcrypto.so.6 (0x00007fe440e41000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fe440b39000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe440836000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe440620000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe44025f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe441e1d000)
libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fe440012000)
libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fe43fd2d000)
libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fe43fb29000)
libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fe43f8f6000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe43f6f2000)
libz.so.1 => /lib64/libz.so.1 (0x00007fe43f4dc000)
libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fe43f2cc000)
libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fe43f0c8000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fe43eeae000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fe43ec88000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fe43ea27000)
liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fe43e802000)

配置的innodb_data_home_dir和innodb_log_home_dir,导致rsync模式的sst传输报错

因为我们的galera集群的配置参数中没有指定:

1
2
#wsrep_sst_method=xtrabackup-v2
#wsrep_sst_auth="xtrabackup:xtrabackuppass"

所以galeta集群在进行sst的时候是通过默认的的rsync方式同步的,但是在这种方式下,不能自定义innodb_data_home_dir和innodb_log_home_dir,这是MariaDB Galera的BUG,如果要自定义这两个参数,可以选择xtrabackup的方式。
wsrep_sst_method可以指定为mysqldump,xtrabackup,rsync三种,xtrabackup的方式锁表时间最短

博客地址:https://win-man.github.io/
公众号:欢迎关注

什么是NFS,为什么要NFS

NFS(Network File System)这个网络文件系统,最大的功能是通过网络,使得在不同的机器之间共享文件。通过NFS可以将另一台机器的某个目录挂载到本机的某个目录下,在使用的时候挂载过来的目录就像在本地一样。极大的方便了多台服务器之间的文件共享。

什么是RPC

在提到NFS服务的时候,都会提到RPC服务,那么什么是RPC服务,为什么需要RPC服务呢。
首先RPC是Remote Procedure Call的缩写,及远程过程调用。其次关于为什么要RPC服务是因为,NFS服务在启动的时候对于端口的选择是随机的,NFS在启动的时候回随机选择小于1024的端口进行数据的传输。那么在客户端连接到NFS服务器的时候,怎么知道应该通过哪个端口进行连接呢。这个时候就需要RPC服务出现了,RPC的主要功能就是记录每个NFS服务所对应的端口号,并将对应的端口号发送给客户端,客户端根据获得的端口号进行连接。
客户端连接NFS服务的过程:

  1. 客户端首先向NFS服务所在的服务器的RPC服务发起请求,RPC服务的端口固定为111
  2. RPC服务在接收到客户端的请求之后,找到注册的NFS服务所对应的端口号,并将端口号发送给客户端
  3. 客户端根据获取到NFS端口号进行连接

配置NFS步骤

  • 环境介绍
    • CentOS6.6

NFS主要软件结构

  • /etc/exports NFS的主要配置文件,在该文件中定义NFS输出的目录、权限等属性
  • /usr/sbin/exportfs 管理NFS共享资源的命令,在NFS的server端使用
  • /usr/sbin/showmount 查询NFS共享资源的命令,在client端使用
  • /var/lib/nfs/etab NFS的日志文件,记录了NFS共享出来的目录的完整权限设置值
  • /var/lib/nfs/xtab NFS连接信息的日志文件,记录了曾经链接到此NFS服务器的相关客户端的数据

/etc/exports配置文件介绍

配置文件中的格式:

1
<输出目录> [客户端1(权限)] [客户端2(权限)] ...

  • 输出目录
    指定共享的文件目录

  • 客户端
    指定可以访问共享资源的客户端

    • 指定IP的方式:192.168.1.1
    • 指定网段的方式 192.168.1.0/24或者192.168.1.0/255.255.255.0
    • 指定主机名的方式 node1,但是这个主机名必须在记录在/etc/hosts文件内,需要能解析到对应的ip
    • 通配符的方式 表示所有的主机,node主机名通配
  • 权限

    • rw/ro 指定文件是可读写(read-write)的还是只读(read-only)的
    • sync/async 对目录中的数据进行更改的话,更改会同步写到硬盘还是只写到内存直接写到硬盘
    • no_root_squash 当客户端使用root账户连接的时候,不转化为匿名用户
    • root_squash 当客户端使用root账户连接的会后,转化为匿名用户
    • all_squash 当客户端连接的时候,无论使用什么用户进行连接,都会被转换为匿名用户
    • anonuid 指定匿名用户的UID
    • anongid 指定匿名用户的GID

NFS server端配置

  • 检查服务器是否安装了nfs-util和rpcbind两个包

    1
    2
    3
    4
    5
    [root@d146bbc8-94a2-42c4-8eaa-3fb3264fd176 ~]# rpm -qa | grep nfs
    nfs-utils-1.2.3-54.el6.x86_64
    nfs-utils-lib-1.1.5-9.el6.x86_64
    [root@d146bbc8-94a2-42c4-8eaa-3fb3264fd176 ~]# rpm -qa | grep rpcbind
    rpcbind-0.2.0-11.el6.x86_64
  • 填写/etc/exports配置文件

    1
    2
    mkdir -p /nfs/{test1,test2,test3,test4,test5}
    vim /etc/exports


exports配置文件中都有默认权限配置,如果我们想查看默认的配置是什么,可以查看/var/lib/nfs/etab文件,该文件中完整的记录了NFS共享资源的所有配置

1
2
3
4
/nfs/test2	10.10.30.247(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
/nfs/test1 10.10.30.247(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
/nfs/test3 10.10.30.0/24(rw,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)
/nfs/test2 *(ro,sync,wdelay,hide,nocrossmnt,secure,root_squash,no_all_squash,no_subtree_check,secure_locks,acl,anonuid=65534,anongid=65534)

  • 启动RPC服务

    1
    [root@d146bbc8-94a2-42c4-8eaa-3fb3264fd176 ~]# /etc/init.d/rpcbind start
  • 启动NFS服务

    1
    2
    3
    4
    5
    6
    [root@d146bbc8-94a2-42c4-8eaa-3fb3264fd176 ~]# /etc/init.d/nfs start
    Starting NFS services: [ OK ]
    Starting NFS quotas: [ OK ]
    Starting NFS mountd: [ OK ]
    Starting NFS daemon: [ OK ]
    Starting RPC idmapd: [ OK ]
  • 修改/etc/exports文件
    如果我们在启动NFS服务之后,又修改了 exports 文件的话怎么办,是不是需要重新启动NFS服务才能使的这些配置生效,答案当然是否定的,这样多麻烦。我们有 exportfs 命令。

    1
    2
    3
    4
    5
    6
    7
    exportfs [-aruv]

    options:
    -a:全部挂载或卸载
    -r:重新挂载/etc/exports配置文件中的信息
    -u:卸载某一目录
    -v:将内容显示输出

client端配置

  • 通过showmount命令查看NFS共享资源的情况
    1
    2
    3
    4
    5
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# showmount -e 10.10.30.250
    Export list for 10.10.30.250:
    /nfs/test3 10.10.30.0/24
    /nfs/test2 (everyone)
    /nfs/test1 10.10.30.247
1
2
3
4
5
showmount [-ae] [hostname|IP]

options:
-a:显示当前主机与客户端的NFS连接情况
-e:显示指定NFS服务器的共享资源情况
  • 挂载NFS目录

    1
    2
    3
    4
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# mkdir -p /nfs/local/{test1,test2,test3}
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# mount 10.10.30.250:/nfs/test1 /nfs/local/test1
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# mount 10.10.30.250:/nfs/test2 /nfs/local/test2
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# mount 10.10.30.250:/nfs/test3 /nfs/local/test3
  • 查看挂载情况

    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
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# df -h
    Filesystem Size Used Avail Use% Mounted on
    /dev/mapper/VolGroup-root
    50G 5.3G 42G 12% /
    tmpfs 1.9G 0 1.9G 0% /dev/shm
    /dev/vda1 488M 31M 432M 7% /boot
    /dev/sda 20G 33M 20G 1% /data
    10.10.30.250:/nfs/test1
    50G 5.3G 42G 12% /nfs/local/test1
    10.10.30.250:/nfs/test2
    50G 5.3G 42G 12% /nfs/local/test2
    10.10.30.250:/nfs/test3
    50G 5.3G 42G 12% /nfs/local/test3
    [root@6a192e7f-a43d-4b57-9573-ca740e3b5f0d ~]# mount
    /dev/mapper/VolGroup-root on / type ext4 (rw)
    proc on /proc type proc (rw)
    sysfs on /sys type sysfs (rw)
    devpts on /dev/pts type devpts (rw,gid=5,mode=620)
    tmpfs on /dev/shm type tmpfs (rw)
    /dev/vda1 on /boot type ext4 (rw)
    none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)
    /dev/sda on /data type xfs (rw,nouuid)
    sunrpc on /var/lib/nfs/rpc_pipefs type rpc_pipefs (rw)
    10.10.30.250:/nfs/test1 on /nfs/local/test1 type nfs (rw,vers=4,addr=10.10.30.250,clientaddr=10.10.30.247)
    10.10.30.250:/nfs/test2 on /nfs/local/test2 type nfs (rw,vers=4,addr=10.10.30.250,clientaddr=10.10.30.247)
    10.10.30.250:/nfs/test3 on /nfs/local/test3 type nfs (rw,vers=4,addr=10.10.30.250,clientaddr=10.10.30.247)

NFS文件访问权限设置

我们知道在Linux系统中的文件,都有访问权限,可以指定用户访问,那么我通过NFS访问文件权限是如何设定的呢。比如我再NFS server上有一个文件的属主与属组都是gangshen,那我再client端普通用户user1访问这个文件,可以做修改吗?如果是使用root用户访问这个文件,可以做修改吗?
NFS文件系统的权限访问的原则是:服务器端会以客户端的用户UID与GID等身份来尝试读取服务器端的文件系统
以下是NFS是如何判断是否一个文件可写的步骤:

  1. 客户端以user1这个账户访问NFS目录,实际是以client端的user1的UID以及GID进行访问的
  2. NFS server收到客户端访问请求中的UID、GID,并根据这个UID在server端所在的服务器找到相应的用户,以该用户的权限进行访问
  3. 如果找不到对应UID的用户,则NFS server端会将连接的身份转换为匿名用户的连接
  4. 根据/etc/exports配置文件判断该目录是否有写入权限
    只有在满足:1、用户有写入权限 2、exports设置为有写入权限 3、文件具有写入权限 这三点之后,客户端才可以写入NFS是共享目录。

根据上述步骤的话,可以想到一种情况,如果我client端是通过root账户连接的,那我是不是对所有的文件具有可读、可写权限。这个的话,就需要重新来看下/etc/exports这个配置文件了。在exports文件中,设定权限的时候可以指定no_root_squash、root_squash、all_squash,这三个就是控制,我client连接上来的用户,最终在server端会以哪个用户进行访问。默认情况下是设置为root_squash,就是说如果client以root用户连接上来的话,server端会将该用户转换为匿名用户进行访问。很明显no_root_squash这个选项就是说不转换成匿名用户,all_squash这个选项是指定无论client用什么账户连接上来,都会被转换成匿名用户。

博客地址:https://win-man.github.io/
公众号:欢迎关注

简介

学习Linux的时候,避不开的就是需要学习Linux中的分区。学习Linux的分区,有很多概念性的东西需要学习,比如分区类型啊,文件系统类型啊…等等,对于我来说,并不是很喜欢这种概念性的东西,上来一大段文字对于我一点都不友好。所以整理了一篇笔记,记录怎么对Linux中的磁盘进行分区、创建文件系统以及挂载。首先能实操使用,接着再慢慢理解其中的内容。

环境介绍

操作系统:CentOS6.6

命令介绍

分区命令

fdisk 分区

fdisk可用于查看硬盘分区情况,也可以使用fdisk进行分区。
选项:

1
2
3
4
5
-b SECTOR_SIZE:指定每个分区大小
-l:列出指定硬盘的分区情况
-s PARTITION:输出指定分区的大小,单位为块
-u:在列出硬盘分区情况的时候,使用块为单位列出分区大小而不是以柱面为单位
-v:显示版本信息

子选项:

1
2
3
4
5
6
7
8
p:print,显示已有分区
n:new,创建
d:delete,删除
w:write,写入磁盘并退出
q:quit,放弃更新并退出
m:获取帮助
l:列表所分区id
t:调整分区id

partx 识别分区

**选项:

1
2
3
4
5
-a:通知内核重新读取硬盘分区表
-d:删除分区硬盘分区表信息
-l:列出分区
--type YTPE:指定分区类型
--nr M-N:指定分区范围

创建文件系统命令

mkfs 创建文件系统

选项:

1
2
3
-t TYPE:指定穿件的文件系统类型
-v:显示版本信息
-c:创建文件系统之前,先检查分区是否存在坏块

mkswap 创建交换分区

选项:

1
2
-c:创建交换分区之前,先检查分区是否存在坏块
-f:强制执行

挂载命令

mount 挂载分区

mount [-fnrsvw] [-t vfstype] [-o options] device dir
选项:

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
-t vsftype:指定要挂载的设备上的文件系统类型
-r :readonly,只读挂载
-w:read and write,读写挂载
-n:不更新/etc/fstab
-a:自动挂载所有支持自动挂载的设备(定义在了/etc/fstab文件中,且挂载选项中有“自动挂载”功能)
-L 'LABEL':以卷标指定挂载设备
-U 'UUID':以UUID指定要挂载的设备
-B,--bind:绑定目录到另一个目录上


-o options:挂载文件系统的选项
async:异步模式
sync:同步模式
atime/noatime:包含目录和文件
diratime/nodiratime:目录的访问时间戳
auto/noauto:是否支持自动挂载
exec/noexec:是否支持将文件系统上的应用程序运行为进程
dev/nodev:是否支持在此文件系统上使用设备
suid/nosuid;
remount:重新挂载
ro:只读挂载
rw:读写挂载
user/nouser:是否允许普通用户挂载此设备
acl:启用此文件系统上acl功能
defaults:rw,suid,dev,exec,auto,nouser,and async

umount 卸载分区

umount [-dflnrv] {dir|device}…
选项:

1
2
3
4
5
6
7
-a:卸除/etc/mtab中记录的所有文件系统;
-h:显示帮助;
-n:卸除时不要将信息存入/etc/mtab文件中;
-r:若无法成功卸除,则尝试以只读的方式重新挂入文件系统;
-t<文件系统类型>:仅卸除选项中所指定的文件系统;
-v:执行时显示详细的信息;
-V:显示版本信息。

swapon 启用交换分区

swapon [-f] [-p priority] [-v] specialfile…
选项:

1
2
-a :激活所有的交换分区
-p PRIORITY:指定优先级

swapoff 禁用交换分区

swapoff [-v] specialfile…
选项:

1
-a:禁用所有的交换分区

步骤介绍

普通分区从创建以及挂载

  • 查看硬盘以及分区情况

    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
    [root@sg-pc /]# lsblk
    NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    sr0 11:0 1 4.3G 0 rom
    sda 8:0 0 20G 0 disk
    ├─sda1 8:1 0 500M 0 part /boot
    └─sda2 8:2 0 19.5G 0 part
    ├─vg_sgpc-lv_root (dm-0) 253:0 0 17.6G 0 lvm /
    └─vg_sgpc-lv_swap (dm-1) 253:1 0 2G 0 lvm [SWAP]
    sdb 8:16 0 20G 0 disk
    [root@sg-pc /]# fdisk /dev/sdb

    WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
    switch off the mode (command 'c') and change display units to
    sectors (command 'u').

    Command (m for help): p

    Disk /dev/sdb: 21.5 GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x179a39d6

    Device Boot Start End Blocks Id System

    Command (m for help):
  • 使用fdisk对/dev/sdb硬盘划分分区,划分3个主分区,每个主分区5G大小,并且划分一个扩展分区,4G大小。

    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
    [root@sg-pc /]# fdisk /dev/sdb

    WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
    switch off the mode (command 'c') and change display units to
    sectors (command 'u').

    Command (m for help): n
    Command action
    e extended
    p primary partition (1-4)
    p
    Partition number (1-4): 1
    First cylinder (1-2610, default 1):
    Using default value 1
    Last cylinder, +cylinders or +size{K,M,G} (1-2610, default 2610): +5G

    Command (m for help): n
    Command action
    e extended
    p primary partition (1-4)
    p
    Partition number (1-4): 2
    First cylinder (655-2610, default 655):
    Using default value 655
    Last cylinder, +cylinders or +size{K,M,G} (655-2610, default 2610): +5G

    Command (m for help): n
    Command action
    e extended
    p primary partition (1-4)
    p
    Partition number (1-4): 3
    First cylinder (1309-2610, default 1309):
    Using default value 1309
    Last cylinder, +cylinders or +size{K,M,G} (1309-2610, default 2610): +5G

    Command (m for help): n
    Command action
    e extended
    p primary partition (1-4)
    e
    Selected partition 4
    First cylinder (1963-2610, default 1963):
    Using default value 1963
    Last cylinder, +cylinders or +size{K,M,G} (1963-2610, default 2610): +2610
    Value out of range.
    Last cylinder, +cylinders or +size{K,M,G} (1963-2610, default 2610):
    Using default value 2610

    Command (m for help): p

    Disk /dev/sdb: 21.5 GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x179a39d6

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 654 5253223+ 83 Linux
    /dev/sdb2 655 1308 5253255 83 Linux
    /dev/sdb3 1309 1962 5253255 83 Linux
    /dev/sdb4 1963 2610 5205060 5 Extended

    Command (m for help): n
    First cylinder (1963-2610, default 1963):
    Using default value 1963
    Last cylinder, +cylinders or +size{K,M,G} (1963-2610, default 2610): +2G

    Command (m for help): p

    Disk /dev/sdb: 21.5 GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x179a39d6

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 654 5253223+ 83 Linux
    /dev/sdb2 655 1308 5253255 83 Linux
    /dev/sdb3 1309 1962 5253255 83 Linux
    /dev/sdb4 1963 2610 5205060 5 Extended
    /dev/sdb5 1963 2224 2104483+ 83 Linux

    Command (m for help): w
    The partition table has been altered!

    Calling ioctl() to re-read partition table.
    Syncing disks.
  • 将新划分的分区加载到硬盘分区表中,并查看分区状态

    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
    [root@sg-pc /]# partx -a /dev/sdb
    BLKPG: Device or resource busy
    error adding partition 1
    BLKPG: Device or resource busy
    error adding partition 2
    BLKPG: Device or resource busy
    error adding partition 3
    BLKPG: Device or resource busy
    error adding partition 4
    BLKPG: Device or resource busy
    error adding partition 5
    [root@sg-pc /]# cat /proc/partitions
    major minor #blocks name

    8 0 20971520 sda
    8 1 512000 sda1
    8 2 20458496 sda2
    8 16 20971520 sdb
    8 17 5253223 sdb1
    8 18 5253255 sdb2
    8 19 5253255 sdb3
    8 20 1 sdb4
    8 21 2104483 sdb5
    253 0 18391040 dm-0
    253 1 2064384 dm-1
  • 为分区创建文件系统,这边就选择/dev/sdb1分区作为示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    [root@sg-pc /]# mkfs -t ext4 -L 'backup' /dev/sdb1
    mke2fs 1.41.12 (17-May-2010)
    Filesystem label=backup
    OS type: Linux
    Block size=4096 (log=2)
    Fragment size=4096 (log=2)
    Stride=0 blocks, Stripe width=0 blocks
    328656 inodes, 1313305 blocks
    65665 blocks (5.00%) reserved for the super user
    First data block=0
    Maximum filesystem blocks=1346371584
    41 block groups
    32768 blocks per group, 32768 fragments per group
    8016 inodes per group
    Superblock backups stored on blocks:
    32768, 98304, 163840, 229376, 294912, 819200, 884736

    Writing inode tables: done
    Creating journal (32768 blocks): done
    Writing superblocks and filesystem accounting information: done

    This filesystem will be automatically checked every 25 mounts or
    180 days, whichever comes first. Use tune2fs -c or -i to override.
  • 通过blkid命令,可以查看硬盘设备的信息

    1
    2
    3
    4
    5
    6
    7
    [root@sg-pc /]# blkid
    /dev/sda1: UUID="5e605252-9e26-4ca0-b353-e3e6028bc6ca" TYPE="ext4"
    /dev/sda2: UUID="drR3Sx-Ht8g-nGFi-2vR3-CD3z-qSjY-PUXiye" TYPE="LVM2_member"
    /dev/mapper/vg_sgpc-lv_root: UUID="9ccc9289-ada6-48b8-82f1-42d2f7edba06" TYPE="ext4"
    /dev/mapper/vg_sgpc-lv_swap: UUID="9c4c6c97-b20d-4548-a249-8d98f6b400f1" TYPE="swap"
    /dev/sdb1: LABEL="backup" UUID="4a7b5acb-fc24-446d-b9e0-a14afbe171d9" TYPE="ext4"
    /dev/sdb2: LABEL="myswap" UUID="79f07b7d-c504-43c2-9e0f-87bee77d59b9" TYPE="swap"
  • 将创建完文件系统的分区挂载指定目录下

    1
    2
    [root@sg-pc /]# mkdir /backup
    [root@sg-pc /]# mount /dev/sdb1 /backup/
  • 检查分区挂载情况

    可以看到/dev/sdb1已经被挂载到/backup目录下了。

交换分区的创建与挂载

交换分区的创建与挂载步骤与普通分区一致,也是先划分分区,然后在分区上创建文件系统,接着是激活交换分区。因为交换分区与普通分区有一点不同,需要先调整分区的分区ID。

  • 将/dev/sdb2分区作为交换分区,首先需要修改/dev/sdb2分区的分区ID

    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
    [root@sg-pc /]# fdisk /dev/sdb

    WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
    switch off the mode (command 'c') and change display units to
    sectors (command 'u').

    Command (m for help): p

    Disk /dev/sdb: 21.5 GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x179a39d6

    Device Boot Start End Blocks Id System
    /dev/sdb1 1 654 5253223+ 83 Linux
    /dev/sdb2 655 1308 5253255 83 Linux
    /dev/sdb3 1309 1962 5253255 83 Linux
    /dev/sdb4 1963 2610 5205060 5 Extended
    /dev/sdb5 1963 2224 2104483+ 83 Linux

    Command (m for help): l

    0 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
    1 FAT12 39 Plan 9 82 Linux swap / So c1 DRDOS/sec (FAT-
    2 XENIX root 3c PartitionMagic 83 Linux c4 DRDOS/sec (FAT-
    3 XENIX usr 40 Venix 80286 84 OS/2 hidden C: c6 DRDOS/sec (FAT-
    4 FAT16 <32M 41 PPC PReP Boot 85 Linux extended c7 Syrinx
    5 Extended 42 SFS 86 NTFS volume set da Non-FS data
    6 FAT16 4d QNX4.x 87 NTFS volume set db CP/M / CTOS / .
    7 HPFS/NTFS 4e QNX4.x 2nd part 88 Linux plaintext de Dell Utility
    8 AIX 4f QNX4.x 3rd part 8e Linux LVM df BootIt
    9 AIX bootable 50 OnTrack DM 93 Amoeba e1 DOS access
    a OS/2 Boot Manag 51 OnTrack DM6 Aux 94 Amoeba BBT e3 DOS R/O
    b W95 FAT32 52 CP/M 9f BSD/OS e4 SpeedStor
    c W95 FAT32 (LBA) 53 OnTrack DM6 Aux a0 IBM Thinkpad hi eb BeOS fs
    e W95 FAT16 (LBA) 54 OnTrackDM6 a5 FreeBSD ee GPT
    f W95 Ext'd (LBA) 55 EZ-Drive a6 OpenBSD ef EFI (FAT-12/16/
    10 OPUS 56 Golden Bow a7 NeXTSTEP f0 Linux/PA-RISC b
    11 Hidden FAT12 5c Priam Edisk a8 Darwin UFS f1 SpeedStor
    12 Compaq diagnost 61 SpeedStor a9 NetBSD f4 SpeedStor
    14 Hidden FAT16 <3 63 GNU HURD or Sys ab Darwin boot f2 DOS secondary
    16 Hidden FAT16 64 Novell Netware af HFS / HFS+ fb VMware VMFS
    17 Hidden HPFS/NTF 65 Novell Netware b7 BSDI fs fc VMware VMKCORE
    18 AST SmartSleep 70 DiskSecure Mult b8 BSDI swap fd Linux raid auto
    1b Hidden W95 FAT3 75 PC/IX bb Boot Wizard hid fe LANstep
    1c Hidden W95 FAT3 80 Old Minix be Solaris boot ff BBT
    1e Hidden W95 FAT1

    Command (m for help): t
    Partition number (1-5): 2
    Hex code (type L to list codes): 82
    Changed system type of partition 2 to 82 (Linux swap / Solaris)

    Command (m for help): w
    The partition table has been altered!

    Calling ioctl() to re-read partition table.

    WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
    The kernel still uses the old table. The new table will be used at
    the next reboot or after you run partprobe(8) or kpartx(8)
    Syncing disks.
  • 创建交换分区的文件系统

    1
    2
    3
    [root@sg-pc /]# mkswap -L 'myswap' /dev/sdb2
    Setting up swapspace version 1, size = 5253248 KiB
    LABEL=myswap, UUID=fee42b41-d38f-498e-a27f-70a962734a26
  • 激活交换分区

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [root@sg-pc /]# free -m
    total used free shared buffers cached
    Mem: 996 642 354 1 112 304
    -/+ buffers/cache: 224 771
    Swap: 2015 0 2015
    [root@sg-pc /]# swapon -a /dev/sdb2
    [root@sg-pc /]# free -m
    total used free shared buffers cached
    Mem: 996 645 350 1 112 304
    -/+ buffers/cache: 228 767
    Swap: 7146 0 7146

分区开机自动挂载

上述的硬盘的分区都是在系统中临时挂载使用的,当系统重启的话,目前我们挂载的分区并不会自动挂载上去,又需要我们执行挂载的步骤,这样很不方便。如果我们需要硬盘分区在系统重启的时候也能自动挂载,我们需要将分区的配置写到/etc/fstab这个文件中。

/etc/fstab文件中每一行代表一个启动的时候需要自动挂载的硬盘分区。
每一行记录友6个字段组成,按照顺序分别为:

  • 要挂载的设备
  • 挂载点
  • 文件系统类型
  • 挂载选项
    一般为defaults
  • 转储频率
    指的是备份频率,0表示不做备份,1表示每天做备份,2表示隔天做备份
  • 自检次序
    0表示不自检
    1表示首先自检,数值越大自检次序越靠后。

示例

我们以上面划分的./dev/sdb1分区为例,将其设置为每次机器重启的时候都会将/dev/sdb1分区挂载到相应的挂载点。

在/etc/fstab文件中添加如图所示的一行,表示每次机器重启的时候,都会将/dev/sdb1分区挂载到/backup挂载点上,并且该分区的文件系统类型为ext4类型,挂载选项是defautls,不备份,不自检。

总结

总的来说,Linux下的硬盘分区以及挂载主要是三个步骤:

  1. 划分分区
  2. 创建文件系统
  3. 挂载分区

    博客地址:https://win-man.github.io/
    公众号:欢迎关注

环境介绍

  • 数据库信息
    主库IP:192.168.1.130
    从库IP:192.168.1.132
    主库MySQL版本:5.6.36
    从库MySQL版本:5.6.35
  • 配置信息
    主从开启GTID复制
    主库参数配置:gtid-mode=ON;enforce-gtid-consistency=ON
    从库参数配置:gtid-mode=ON,enforce-gtid-consistency=ON;log-slave-update=ON;master_info_repository=TABLE;relay_log_info_repository=TABLE

测试步骤

  • 搭建主从复制,搭建步骤在此省略
  • 使用Xtrabackup备份从库数据

    1
    2
    3
    4
    备份从库
    [root@host-192-168-1-132 backup]# innobackupex --defaults-file=/etc/my.cnf --user=xtrabackup --password=xtrabackup --slave-info --no-timestamp /tmp/backup
    应用日志
    [root@host-192-168-1-132 backup]# innobackupex --defaults-file=/etc/my.cnf --apply-log /tmp/backup
  • 清空从库数据,并使用备份恢复从库

    1
    2
    [root@host-192-168-1-132 mysqldata1]# innobackupex --defaults-file=/etc/my.cnf --copy-back /tmp/backup/
    [root@host-192-168-1-132 mysqldata1]# chown -R mysql:mysql /home/mysql
  • 查看xtrabckup中备份的slave信息

    1
    2
    3
    [root@host-192-168-1-132 backup]# cat xtrabackup_slave_info 
    SET GLOBAL gtid_purged='05dff9fd-5c97-11e7-b3f4-fa163ea44438:1-7';
    CHANGE MASTER TO MASTER_AUTO_POSITION=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
    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
    [root@host-192-168-1-132 mysqldata1]# service mysqld start

    mysql> show slave status\G
    *************************** 1. row ***************************
    Slave_IO_State:
    Master_Host: 192.168.1.130
    Master_User: repl
    Master_Port: 6306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000002
    Read_Master_Log_Pos: 1615
    Relay_Log_File: mysql-relay-bin.000002
    Relay_Log_Pos: 649
    Relay_Master_Log_File: mysql-bin.000002
    Slave_IO_Running: No
    Slave_SQL_Running: No
    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: 1856
    Relay_Log_Space: 0
    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: 0
    Last_IO_Error:
    Last_SQL_Errno: 0
    Last_SQL_Error:
    Replicate_Ignore_Server_Ids:
    Master_Server_Id: 0
    Master_UUID: 05dff9fd-5c97-11e7-b3f4-fa163ea44438
    Master_Info_File: mysql.slave_master_info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State:
    Master_Retry_Count: 86400
    Master_Bind:
    Last_IO_Error_Timestamp:
    Last_SQL_Error_Timestamp:
    Master_SSL_Crl:
    Master_SSL_Crlpath:
    Retrieved_Gtid_Set:
    Executed_Gtid_Set:
    Auto_Position: 1
    1 row in set (0.00 sec)

    mysql> show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000001 | 151 | | | |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)

    mysql> set global gtid_purged='05dff9fd-5c97-11e7-b3f4-fa163ea44438:1-7';
    Query OK, 0 rows affected (0.08 sec)

    mysql> start slave;
    ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
  • start slave的时候出现错误,于是重置了slave信息,重新change 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
    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
    mysql> reset slave all;
    Query OK, 0 rows affected (0.03 sec)

    mysql> change master to
    -> master_host='192.168.1.130',
    -> master_user='repl',
    -> master_password='repl',
    -> master_port=6306,
    -> master_auto_position=1;
    Query OK, 0 rows affected, 2 warnings (0.35 sec)

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

    mysql> show slave status\G
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 192.168.1.130
    Master_User: repl
    Master_Port: 6306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000002
    Read_Master_Log_Pos: 1856
    Relay_Log_File: mysql-relay-bin.000002
    Relay_Log_Pos: 408
    Relay_Master_Log_File: mysql-bin.000002
    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: 1856
    Relay_Log_Space: 612
    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: 0
    Master_SSL_Verify_Server_Cert: No
    Last_IO_Errno: 0
    Last_IO_Error:
    Last_SQL_Errno: 0
    Last_SQL_Error:
    Replicate_Ignore_Server_Ids:
    Master_Server_Id: 3656
    Master_UUID: 05dff9fd-5c97-11e7-b3f4-fa163ea44438
    Master_Info_File: mysql.slave_master_info
    SQL_Delay: 0
    SQL_Remaining_Delay: NULL
    Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
    Master_Retry_Count: 86400
    Master_Bind:
    Last_IO_Error_Timestamp:
    Last_SQL_Error_Timestamp:
    Master_SSL_Crl:
    Master_SSL_Crlpath:
    Retrieved_Gtid_Set:
    Executed_Gtid_Set: 05dff9fd-5c97-11e7-b3f4-fa163ea44438:1-7
    Auto_Position: 1
    1 row in set (0.00 sec)

总结

  • XtraBackup备份从库的时候,利用备份恢复数据之后,第一次启动数据库的时候,不会启动I/O线程和SQL线程
  • Xtrabackup备份从库,虽然保存了原先slave中chang master to的信息,但是不能直接start slave;需要reset slave all之后重新指定主库信息
  • Xtrabackup备份从库,不会备份GTID_PURGED的信息,需要恢复的时候,自己指定

博客地址:https://win-man.github.io/
公众号:欢迎关注

简介

在《高性能MySQL》上看到说在一主多从的架构中,如果从库的sever_id设置为一样的,可能会导致一些奇怪的现象,例如从库的错误日志中会不断的打印错误日志,会不断的断开连接并重新连接。

在主库上,会发现两台备库只有一台连接到主库(通常情况下所有的备库都会建立连接等待随时进行复制)。在备库的错误日志中,则会发现反复的重连和连接断开信息,但不会提及被错误配置的服务器ID。

根据眼见为实,耳听为虚的原则,我搭了一套一主两从的环境,将两台从库的server_id设置为了一样的。但是并没有看到书上提到的现象。考虑了一下,会不会是数据库版本的原因,因为我的测试的数据库版本是5.7.18版本的。于是又重新搭建了一套5.5.36版本的数据库,并成功复现了书上所讲的现象。
下面是我的测试步骤。

测试步骤

环境介绍

  • 主库
    IP:192.168.1.130
    server_id:3656
  • 从库A
    IP:192.168.1.36
    server_id:56
  • 从库B
    IP:192.168.1.57
    server_id:56

三台主机除server_id之外,其余配置如下:

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
server_id = 123
[client]
socket = /home/mysql/data/mysqldata5.5/sock/mysql.sock
[mysqld]
#server_id = 3655
server_id = 123
port = 3306
skip_name_resolve = 1
binlog_format = ROW
#binlog_format = STATEMENT
basedir = /home/mysql/program/mysql5.5.36
datadir = /home/mysql/data/mysqldata5.5/mydata
socket = /home/mysql/data/mysqldata5.5/sock/mysql.sock
pid-file = /home/mysql/data/mysqldata5.5/sock/mysql.pid
tmpdir = /home/mysql/data/mysqldata5.5/tmpdir
log-error = /home/mysql/data/mysqldata5.5/log/error.log
slow_query_log
slow_query_log_file = /home/mysql/data/mysqldata5.5/slowlog/slow-query.log
log-bin = /home/mysql/data/mysqldata5.5/binlog/mysql-bin
relay-log = /home/mysql/data/mysqldata5.5/relaylog/mysql-relay-bin
innodb_data_home_dir = /home/mysql/data/mysqldata5.5/innodb_ts
innodb_log_group_home_dir = /home/mysql/data/mysqldata5.5/innodb_log
#innodb_undo_directory = /home/mysql/data/mysqldata5.5/undo/
sync_binlog=1
innodb_file_per_table=1
#skip_grant_tables
expire_logs_days = 1
log_slave_updates = ON
#replicate-same-server-id=1
skip_slave_start
#innodb_undo_tablespaces=1

5.5.36版本现象

初始搭建环境之后,查看各主机状态。搭建环境的步骤就省略。

主库(192.168.1.130)

主库通过show processlist语句查看,只有一个dump线程,但是通过多次刷新,可以看到连接的是不同的服务器。可以看到每次通过show processlist语句显示的dump线程的Host字段中,IP:PORT的值是不断在更新的,说明dump线程在不断的重连,才会出现占用不同的端口的现象。

从库A(192.168.1.36)

通过show slave status\G命令查看复制状态,多次执行可以看到Slave_IO_Running字段显示的内容,出现YES或者Connnecting两种状态。可以看到I/O线程在不断的进行重连。
并且通过tail -f命令查看error log,可以看到I/O线程一直在尝试重新连接。

可以看到在错误日志中打印的信息是,I/O线程连接

从库B(192.168.1.57)

从库B现象与从库A一致。

5.6.36版本现象

搭建环境步骤省略。

主库(192.168.1.130)

show processlist查看有两个dump线程,并且多次刷新,发现Host字段中的IP:PORT并没有修改,说明dump线程一直保持连接。

从库A(192.168.1.36)

tail -f /home/mysql/data/mysqldata5.6/log/error.log查看错误日志,没有不断断开连接

从库B(192.168.1.57)

tail -f /home/mysql/data/mysqldata5.6/log/error.log查看错误日志,没有不断断开连接

原因分析

http://www.penglixun.com/tech/database/mysql_multi_slave_same_serverid.html这是彭大大写的关于多个slave使用相同server_id时冲突的原因。按照彭大大的分析,我理解的是,slave的I/O线程连接上主库的时候,主库上会调用register_slave()这个函数,在这个函数中又调用了unregister_slave()函数,会将之前使用相同server_id的线程给注销掉。从而导致从库的I/O线程不断断开重连。
但是仔细看了一下unregister_slave()函数的代码,并没有发现MySQL是根据server_id来注销dump线程的。并且进一步比较了一下5.5.36和5.6.36版本的代码,并没有发现不同。
进一步看了一下彭大大的文章,发现有人在下面评论,说主要是kill_zombie_slave_threads()函数导致的。于是看了一下kill_zombie_slave_threads()函数的逻辑,发现MySQL应该就是在这一步根据server_id将线程kill了。

  • 5.5.36版本
    首先来看下5.5.36版本的kill_zombie_dump_threads()函数的代码。看到这个函数传入的参数是一个uint32类型的slave_server_id,在函数中做的事情是,遍历MySQL中的所有线程,如果遍历到一个线程是dump线程并且线程的server_id是等于传入的参数值话,则跳出遍历循环,并对kill掉这个线程。

    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
    void kill_zombie_dump_threads(uint32 slave_server_id)                           
    {
    mysql_mutex_lock(&LOCK_thread_count);
    I_List_iterator<THD> it(threads);
    THD *tmp;
    while ((tmp=it++))
    {
    if (tmp->command == COM_BINLOG_DUMP &&
    tmp->server_id == slave_server_id)
    {
    mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
    break;
    }
    }
    mysql_mutex_unlock(&LOCK_thread_count);
    if (tmp)
    {
    /*
    Here we do not call kill_one_thread() as
    it will be slow because it will iterate through the list
    again. We just to do kill the thread ourselves.
    */
    tmp->awake(THD::KILL_QUERY);
    mysql_mutex_unlock(&tmp->LOCK_thd_data);
    }
    }
  • 5.6.35版本
    再来看一下5.6.36版本的kill_zombie_dump_threads()函数的代码实现,与5.5.36大不相同。首先传入的参数是一THD类型的指针,在函数中实现的逻辑同样是遍历MySQL中的所有线程,如果找到dump线程,首先看一下这个线程有没有uuid字段(因为uuid是在5.6之后的版本才有的,这边是为了兼容5.5),如果有uuid则用uuid进行比较,如果没有uuid,则用server_id进行比较。

    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
     void kill_zombie_dump_threads(THD *thd)                                                                                                  
    {
    String slave_uuid;
    get_slave_uuid(thd, &slave_uuid);
    if (slave_uuid.length() == 0 && thd->server_id == 0)
    return;

    mysql_mutex_lock(&LOCK_thread_count);
    THD *tmp= NULL;
    Thread_iterator it= global_thread_list_begin();
    Thread_iterator end= global_thread_list_end();
    bool is_zombie_thread= false;
    for (; it != end; ++it)
    {
    if ((*it) != thd && ((*it)->get_command() == COM_BINLOG_DUMP || (*it)->get_command() == COM_BINLOG_DUMP_GTID))
    {
    String tmp_uuid;
    get_slave_uuid((*it), &tmp_uuid);
    if (slave_uuid.length())
    {
    is_zombie_thread= (tmp_uuid.length() && !strncmp(slave_uuid.c_ptr(),
    tmp_uuid.c_ptr(), UUID_LENGTH));

    else
    {
    /*
    ¦ Check if it is a 5.5 slave's dump thread i.e., server_id should be
    ¦ same && dump thread should not contain 'UUID'.
    */
    is_zombie_thread= (((*it)->server_id == thd->server_id) && !tmp_uuid.length());
    }
    if (is_zombie_thread)
    {
    tmp= *it;
    mysql_mutex_lock(&tmp->LOCK_thd_data); // Lock from delete
    break;
    }
    }
    }
    mysql_mutex_unlock(&LOCK_thread_count);
    if (tmp)
    {
    /*
    ¦ Here we do not call kill_one_thread() as
    ¦ it will be slow because it will iterate through the list
    ¦ again. We just to do kill the thread ourselves.
    */
    if (log_warnings > 1)
    {
    if (slave_uuid.length())
    {
    sql_print_information("While initializing dump thread for slave with "
    "UUID <%s>, found a zombie dump thread with the "
    "same UUID. Master is killing the zombie dump "
    "thread(%lu).", slave_uuid.c_ptr(),
    tmp->thread_id);
    }
    else
    {
    sql_print_information("While initializing dump thread for slave with "
    "server_id <%u>, found a zombie dump thread with the "
    "same server_id. Master is killing the zombie dump "
    "thread(%lu).", thd->server_id,
    tmp->thread_id);
    }
    }
    tmp->duplicate_slave_id= true;
    tmp->awake(THD::KILL_QUERY);
    mysql_mutex_unlock(&tmp->LOCK_thd_data);
    }
    }
  • 函数调用
    知道了kill_zombie_dump_threads()线程实现的逻辑,那MySQL是在什么地方会调用这个函数的呢。看了一下函数是在case COM_BINLOG_DUMP中被调用的。
    在5.5.36版本中是在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    case COM_BINLOG_DUMP:                                                         
    {
    ulong pos;
    ushort flags;
    uint32 slave_server_id;
    status_var_increment(thd->status_var.com_other);
    thd->enable_slow_log= opt_log_slow_admin_statements;
    if (check_global_access(thd, REPL_SLAVE_ACL))
    break;
    /* TODO: The following has to be changed to an 8 byte integer */
    pos = uint4korr(packet);
    flags = uint2korr(packet + 4);
    thd->server_id=0; /* avoid suicide */
    if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
    kill_zombie_dump_threads(slave_server_id);
    thd->server_id = slave_server_id;
    general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10, (long) pos);
    mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
    unregister_slave(thd,1,1);
    /* fake COM_QUIT -- if we get here, the thread needs to terminate */
    error = TRUE;
    break;
    }

在5.6.36版本中也是在case COM_BINLOG_DUMP中,只不过是将之前的逻辑封装在了com_binlog_dump()函数中了,kill_zombie_dump_threads()也是在com_binlog_dump()函数中调用的。

1
2
3
case COM_BINLOG_DUMP:                                                         
error= com_binlog_dump(thd, packet, packet_length);
break;

case COM_BINLOG_DUMP中所进行的操作就是将dump线程通知I/O线程拉取新的binlog。

总结

整理下来的话,基本上可以确定主要是因为kill_zombie_dump_threads()函数导致在5.6之前的版本中,如果是一主多从的架构中,如果在从库之间的server_id如果设置为一样,会出现从开I/O线程不断断开重连的现象。因为在5.6之前的版本中,还没有UUID的概念,MySQL使用server_id来区分是否是同一台机器,而在5.6之后的版本是使用的UUID来区分。
总结一句,就是数据库之间的server_id不要设置成一样,不然可能会有一些不可预知的错误。

博客地址:https://win-man.github.io/
公众号:欢迎关注

  其实这篇年终总结早就想写了,可是拖延症犯了,一直拖啊拖啊,已经拖过了 2016 与 2017 年的交界,可是作为一名中国人,我为什么一定要以公历年份来划分我的时间呢,我选择猴年与鸡年来划分我的时间。所以,这篇总结不算晚。

1.回顾

1.1 实习

  过去的一年,由我大三下与大四上组成。从一开始就没有考研的打算,实习便成为了我的一年的主要内容。

  第一段实习经历是在实验室老师成立的公司,做了一段时间的 Java 开发,之后选择了换一家公司。原因总结来说的话,就是看不到未来,那时候还有一点技术改变世界的想法,感觉做出来的产品完全称不上是一个产品,简直就是学校里一个课程设计。老板出去还把这产品吹的天花乱坠的,实际上完全是另一回事。所以果断弃坑。

  第二段实习经历,主要是为了完成学院的实习要求,还是做 Java 开发。中间过程没有一点可言的。不过也要感谢这段实习经历,让我有时间静下来,学一些东西。也就是在这个期间,我将我的博客从 CSDN 转到了 GitHub,加入了 itsCoder ······ 让我有时间去做我想做的事情了。最后完成学院要求之后,还是毅然决然的离开了,因为不明白,为什么一个成立时间不到两年的一个公司,整天的气氛是死气沉沉的,没有技术氛围。

  第三段实习经历,就是目前正在经历着的。结束上一段实习经历的时候,我就打算这次好好找一个实习,奔着毕业之后转正的目的找的。投了一波简历,面了一波试。在最后选择了现在的公司,并且完成了转型,从开发转行成为了一名 DBA 。到目前为止,我想我应该是找到了我想要的工作。

1.2 学习

  学习这方面的话,整体上进度是不大的。花了前面大半年的时间,都是在学习开发方面的内容,学框架,学技术,学算法,最后怎么也没想到直接从开发转行了,所以学的很多东西对于工作来说,意义不大了。转行 DBA,开始接触数据库开始,才发现原来数据库水这么深,之前理解的数据库就是一个数据的增删改查,之后发现这就是一个新的世界。

1.3 其余

  过去的一年,算是崩坏的一年。

  身体没有好好锻炼,锻炼一段时间歇一段时间的;

  书没好好读,好多书都是走马观花的浏览了一遍,也没看到心里去;

  习惯没有好好养成,有很多习惯想要养成,现在看来一个也没成功;

  计划没有好好执行,计划任然是计划。

  一年时间,体重飙涨20斤,还好及时发现,狠命锻炼一段时间,减到 70KG ,目前仍维持着。

  自控力下降,执行力降低。

  上一张 Github 2016 年的记录,最难做到的还是坚持:

2.总结

  一句话总结我过去的猴年:瞎搞
  本来一开始想去大公司开始实习的,准备准备,干一波春招。结果被老师打乱了节奏,三段实习经历,公司都不大,但也发现了小公司的好处。自由。不打卡,可以有自己的话语权,公司同事整体年龄比较年轻,有活力。

  一年下来,没有多少收获,只是找到了之后的职业方向,对自己职业也有了初步的规划。我觉得有这一点也已经够了。

3.计划

  又到了制定计划的时候了,把话撂在这,等着明年来打脸(注定的:

  1. 顺利毕业
  2. 读 35 本书,至少完成 20 本书的读书笔记或感想
  3. 12 篇认真完成的博客
  4. 保证规律的作息时间,不熬夜,11点准时睡觉
  5. 锻炼,保证每周至少三次的锻炼
  6. 出去走走,一个人也好,两个人也好

博客地址:https://win-man.github.io/
公众号:欢迎关注

1. 前言

  之前讲了如何安装 Tmux,这篇文章讲讲如何使用 Tmux。其实工具的使用都是很简单,最终是看你如何使用这个工具,才能发挥出工具最大的作用。

2. 基础知识

  在讲如何使用 Tmux 之前,我们需要先熟悉它的几个概念。

  • 会话(Session)
  • 窗口(Window)
  • 面板(Pane)

会话:会话的概念很好理解。我们一台服务器正在那边运行着,我们拿终端工具如:XShell、SecureCRT 等去连接的时候,每新建一个连接,就是一个新的会话。使用 Tmux 新建会话的时候,也是一样,一个新的会话就表示一个新的连接。

窗口:窗口的概念,可以类比于 Windows 里面的窗口的概念。之前我们连服务器的时候,终端工具每次连接只有一个界面,当我们需要同时操作多个过程的时候,我们就需要建立新的连接。这样很不方便。Tmux 里面的窗口的概念,就可以让我们在一个会话里有多个界面,就不需要去建立的一个会话。

面板:面板的概念的话,是用于对界面的布局而言的。就是将一个界面划分为多个不同的区域,每个区域我们称之为一个面板。

  简单来说就是,一个会话里面可以有多个窗口,一个窗口里面可以有多个面板。

3. 命令行使用方式

  Tmux 可以有两种使用方式,一种是命令行的方式,一种是快捷键的方式。前者的话不需要怎么记忆,后者的话效率更高。我觉得还是命令行入门,先熟悉这个工具的作用,之后将常用的几个功能的快捷键记下来,多使用,多熟练。

3.1 会话操作

1
$ tmux new -s [session_name]  //  创建一个会话

创建完会话之后,会自动进入这个会话之内。并且会话默认帮你创建好一个窗口。

1
$ tmux list-sessions // 显示所有会话,也可以简写成 tmux ls

当前的话,我一共有一个会话,并且会话的名称为: session1 。

1
2
3
4
5
$ tmux detach // 退出当前的会话,返回 shell 界面
$ tmux kill-session -t [session_name ] // 结束一个会话
$ tmux attach -t [session_name] // 回到某一个会话当中
$ tmux switch -t [session_name] // 切换到某一会话当中
$ tmux kill-server // 关闭所有会话

3.2 窗口操作

  讲完会话的操作,我们来讲讲窗口的操作。

1
$ tmux new-window [-n window_name] // 创建一个新的窗口,可以指定新的窗口的名字也可以不指定

这边,我新建了一个名为 window1 的窗口,并且 Tmux 自动帮我切换到了这个窗口,* 标记当前正在使用的窗口,一个窗口默认包含一个面板。

1
$ tmux rename-window [new_window_name] // 重命名当前窗口的名字

1
$ tmux list-windows // 显示当前会话中所有的窗口

1
2
$ tmux kill-window -t [window_name | window_index] // 关闭一个窗口
$ tmux select-window -t [window_index] // 切换窗口

3.3 面板操作

1
2
$ tmux split-window //将一个面板垂直切成两个面板
$ tmux split-window -h // 将一个面板水平切成两个面板

可以看到图片中的话,我将一个窗口切成了三部分区域,每一个区域都是一个面板。

1
2
$ tmux swap-pane -[UDRL] // 选择 [ 上下左右 ] 的面板交换
$ tmux select-pane -[UDRL] // 选择 [ 上下左右 ] 的面板进行切换

  以上的话就是同过命令行的方式使用 Tmux,使用命令行的方式,可以简单了解一下 Tmux 这个工具提供的一些功能。接下来就是进阶的,使用快捷键的方式操作 Tmux。

4. 快捷键使用方式

  Tmux 快捷键的话需要先按下前缀键,之后再按快捷键才会有效果。 Tmux 默认的前缀键是 Ctrl + b。我就只简单罗列一下快捷键,实际效果的话,使用一下就知道了,上面使用命令行能达到的功能,都能找到相应的快捷键。

  Tmux 还有一个配置文件,可以根据自己的习惯将快捷键改成自己喜欢的键。

4.1 基本操作

1
2
3
4
5
6
7
8
9
10
? 列出所有快捷键;按q返回
d 脱离当前会话,可暂时返回Shell界面
s 选择并切换会话;在同时开启了多个会话时使用
D 选择要脱离的会话;在同时开启了多个会话时使用
: 进入命令行模式;此时可输入支持的命令,例如 kill-server 关闭所有tmux会话
[ 复制模式,光标移动到复制内容位置,空格键开始,方向键选择复制,回车确认,q/Esc退出
] 进入粘贴模式,粘贴之前复制的内容,按q/Esc退出
~ 列出提示信息缓存;其中包含了之前tmux返回的各种提示信息
t 显示当前的时间
ctrl + z 挂起当前会话

4.2 窗口操作

1
2
3
4
5
6
7
8
9
10
c 创建新窗口
& 关闭当前窗口
[0-9] 数字键切换到指定窗口
p 切换至上一窗口
n 切换至下一窗口
l 前后窗口间互相切换
w 通过窗口列表切换窗口
, 重命名当前窗口,便于识别
. 修改当前窗口编号,相当于重新排序
f 在所有窗口中查找关键词,便于窗口多了切换

4.3 面板操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
" 将当前面板上下分屏
% 将当前面板左右分屏
x 关闭当前分屏
! 将当前面板置于新窗口,即新建一个窗口,其中仅包含当前面板
ctrl+方向键 以1个单元格为单位移动边缘以调整当前面板大小
alt+方向键 以5个单元格为单位移动边缘以调整当前面板大小
q 显示面板编号
o 选择当前窗口中下一个面板
方向键 移动光标选择对应面板
{ 向前置换当前面板
} 向后置换当前面板
alt+o 逆时针旋转当前窗口的面板
ctrl+o 顺时针旋转当前窗口的面板
z 最大化当前所在面板
page up 向上滚动屏幕,q 退出
page down 向下滚动屏幕,q 退出

5. 总结

  说到底 Tmux 也就是这么一个工具,功能也就这么多,但是将 Tmux 和 Vim 结合起来的时候,效果就不一样了,在命令行下开发,整个逼格一下就上去了。装逼使人进步。

博客地址:https://win-man.github.io/
公众号:欢迎关注

1.前言

  Linux 命令行装逼利器——Tmux。转行 DBA 之后整天和命令行打交道,在装逼的道路上越走越远了。Tmux 是 Linux 命令行下一个工具,让我可以更加方便的装逼。先讲一下怎么安装这个工具,之后再写一篇文章记录一下怎么使用这个工具。

系统环境:

CentOS 6.5

2.安装过程

  tmux 工具依赖于 libeventncurses 两个软件包。我们先安装这两个软件包。

2.1 libevent 安装

1
2
3
4
5
6
7
8
9
10
// 下载 tar.gz 文件  
// 可以在 http://libevent.org/ 网站上找到最新版本
$ wget https://cloud.github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
// 解压 tar.gz 文件
$ tar zxvf libevent-2.0.21-stable.tar.gz
$ cd libevent-2.0.21-stable
// 配置安装路径并编译安装,这边可能会出现127错误,可以在./configure中加上--without-cxx-binding参数
$ ./configure --prefix=/usr/local/libevent
$ make
$ make install

2.2 ncurses 安装

1
$ yum install ncurses-devel

2.3 tmux 安装

1
2
3
4
5
6
7
8
9
// 下载 tar.gz 文件 在 https://tmux.github.io/ 可以下载到最新版
$ wget https://github.com/tmux/tmux/releases/download/2.3/tmux-2.3.tar.gz
// 解压 tar.gz 文件
$ tar zxvf tmux-2.3.tar.gz
$ cd tmux-2.3
// 配置安装参数并编译安装
$ CFLAGS="-I/usr/local/libevent/include -I/usr/local/ncurses/include" LDFLAGS="-L/usr/local/libevent/lib -L/usr/local/ncurses/lib" ./configure --prefix=/usr/local/tmux
$ make
$ make install

2.4 配置 PATH 环境变量

在 /etc/profile 最末尾增加 PATH=$PATH:/usr/local/tmux/bin,并使用 source 命令生效。

1
2
// 将 tmux 拷贝到环境变量目录下
$ cp /usr/local/tmux/bin/tmux /usr/local/bin/

3.错误及解决方案

3.1 问题一

  运行 tmux 命令提示 libevent-2.0.so.5 找不到。

  解决方案

1
2
// 将 libevent-2.0.so.5 移动到 /usr/lib64 下(64位操作系统) | /usr/lib 下(32位操作系统)
$ cp /usr/local/libevent/lib/libevent-2.0.so.5 /usr/lib64

博客地址:https://win-man.github.io/
公众号:欢迎关注