diff options
Diffstat (limited to 'src/mariadb-push-replica.sh')
-rwxr-xr-x | src/mariadb-push-replica.sh | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/src/mariadb-push-replica.sh b/src/mariadb-push-replica.sh new file mode 100755 index 0000000..c8e1e0a --- /dev/null +++ b/src/mariadb-push-replica.sh | |||
@@ -0,0 +1,221 @@ | |||
1 | #!/bin/bash | ||
2 | set -e | ||
3 | PATH=$(dirname "$0"):$PATH | ||
4 | source rpc.bash | ||
5 | |||
6 | datadir=data | ||
7 | default_replica_host_file=$datadir/default-replica-host | ||
8 | replication_password_file=$datadir/replication-password | ||
9 | |||
10 | if [ -r "$default_replica_host_file" ] | ||
11 | then | ||
12 | read default_replica_host < "$default_replica_host_file" | ||
13 | fi | ||
14 | |||
15 | gen_password() | ||
16 | { | ||
17 | generated_password_length=32 | ||
18 | generated_password=$(tr -cd a-zA-Z0-9 < /dev/urandom | | ||
19 | head -c "$generated_password_length") | ||
20 | [ "${#generated_password}" -eq "$generated_password_length" ] | ||
21 | printf '%s\n' "$generated_password" | ||
22 | } | ||
23 | |||
24 | if ! [ -e "$replication_password_file" ] | ||
25 | then | ||
26 | gen_password > "$replication_password_file" | ||
27 | fi | ||
28 | |||
29 | if [ -r "$replication_password_file" ] | ||
30 | then | ||
31 | read replication_password < "$replication_password_file" | ||
32 | [ "${#replication_password}" -ge 30 ] | ||
33 | fi | ||
34 | |||
35 | primary_host=$(hostname --fqdn) | ||
36 | replica_host=${1:-$default_replica_host} | ||
37 | replication_user=replication | ||
38 | |||
39 | [ "$primary_host" ] | ||
40 | [ "$replica_host" ] | ||
41 | [ "$replication_password" ] | ||
42 | |||
43 | run_primary() | ||
44 | { | ||
45 | (set -x | ||
46 | : primary : $1 $2 ${3:+ ...}) | ||
47 | BASH_RPC_REMOTE_DEST=$primary_host remote_run_function "$@" | ||
48 | } | ||
49 | |||
50 | run_replica() | ||
51 | { | ||
52 | (set -x | ||
53 | : replica : $1 $2 ${3:+ ...}) | ||
54 | BASH_RPC_REMOTE_DEST=$replica_host remote_run_function "$@" | ||
55 | } | ||
56 | |||
57 | show_hostnames() | ||
58 | { | ||
59 | printf \ | ||
60 | "==> %s %s <==\n %s\n" \ | ||
61 | "$(hostname -A)" \ | ||
62 | "$(hostname -I)" \ | ||
63 | "$(uptime)" | ||
64 | } | ||
65 | |||
66 | check_db() | ||
67 | { | ||
68 | show_hostnames | ||
69 | mariadb --skip-reconnect -t <<END | ||
70 | select @@hostname, @@server_id, @@gtid_slave_pos, @@sql_log_bin; | ||
71 | END | ||
72 | } | ||
73 | |||
74 | create_backup() | ||
75 | { | ||
76 | set -e | ||
77 | mariabackup_target_dir=/var/mariadb/backup | ||
78 | binlog_info_file=$mariabackup_target_dir/xtrabackup_binlog_info | ||
79 | [ -e "$binlog_info_file" ] && return | ||
80 | mkdir -p "$mariabackup_target_dir" | ||
81 | marialog=$(mktemp) | ||
82 | e=0 | ||
83 | (set -- \ | ||
84 | -u root \ | ||
85 | --target-dir="$mariabackup_target_dir" | ||
86 | exec >"$marialog" 2>&1 | ||
87 | set -x | ||
88 | mariabackup --backup --rsync "$@" | ||
89 | mariabackup --prepare "$@") || e=$? | ||
90 | if [ "$e" = 0 -a -e "$binlog_info_file" ] | ||
91 | then | ||
92 | tail -v -n2 "$marialog" >&2 | ||
93 | rm "$marialog" | ||
94 | else | ||
95 | cat "$marialog" >&2 | ||
96 | false | ||
97 | fi | ||
98 | } | ||
99 | |||
100 | delete_backup() | ||
101 | { | ||
102 | set -x | ||
103 | rm -r /var/mariadb/backup | ||
104 | } | ||
105 | |||
106 | send_backup() | ||
107 | { | ||
108 | mariabackup_target_dir=/var/mariadb/backup | ||
109 | set -x | ||
110 | rsync -zaR -- /./"${mariabackup_target_dir#/}" "$1":/ | ||
111 | } | ||
112 | |||
113 | stop_database_server_and_remove_database_files() | ||
114 | { | ||
115 | livedb=/var/lib/mysql | ||
116 | set -e | ||
117 | if [ -e "$livedb" ] | ||
118 | then | ||
119 | if [ "$(systemctl is-active mariadb)" = active ] | ||
120 | then | ||
121 | systemctl stop mariadb | ||
122 | fi | ||
123 | livedb_backup=$livedb~$(date -Ins) | ||
124 | mv -v -T -- "$livedb" "$livedb_backup" | ||
125 | mkdir "$livedb" | ||
126 | chown --reference="$livedb_backup" "$livedb" | ||
127 | chmod --reference="$livedb_backup" "$livedb" | ||
128 | fi | ||
129 | } | ||
130 | |||
131 | restore_from_backup() | ||
132 | { | ||
133 | mariabackup_target_dir=/var/mariadb/backup | ||
134 | set -e | ||
135 | |||
136 | stop_database_server_and_remove_database_files | ||
137 | |||
138 | marialog=$(mktemp) | ||
139 | exec >"$marialog" 2>&1 | ||
140 | set -- \ | ||
141 | -u root \ | ||
142 | --target-dir="$mariabackup_target_dir" | ||
143 | if mariabackup --move-back "$@" | ||
144 | then | ||
145 | tail -v -n2 "$marialog" >&2 | ||
146 | # Can't believe mariabackup | ||
147 | # is so primitive as to | ||
148 | # recommend this chown in its | ||
149 | # documentation | ||
150 | chown -R mysql:mysql /var/lib/mysql | ||
151 | systemctl start mariadb | ||
152 | else | ||
153 | cat "$marialog" >&2 | ||
154 | fi | ||
155 | |||
156 | } | ||
157 | |||
158 | enable_replication() | ||
159 | { | ||
160 | primary_host=$1 | ||
161 | replication_user=$2 | ||
162 | replication_password=$3 | ||
163 | mariabackup_target_dir=/var/mariadb/backup | ||
164 | binlog_info_file=$mariabackup_target_dir/xtrabackup_binlog_info | ||
165 | set -e | ||
166 | read master_log_file master_log_pos gtid_slave_pos < $binlog_info_file | ||
167 | tee /dev/stderr <<END | mariadb --skip-reconnect -t | ||
168 | STOP SLAVE; | ||
169 | SET GLOBAL gtid_slave_pos = "$gtid_slave_pos"; | ||
170 | CHANGE MASTER TO | ||
171 | MASTER_HOST='$primary_host', | ||
172 | MASTER_USER='$replication_user', | ||
173 | MASTER_PASSWORD='$replication_password', | ||
174 | MASTER_USE_GTID=slave_pos; | ||
175 | START SLAVE; | ||
176 | SHOW SLAVE STATUS\G | ||
177 | END | ||
178 | set -x | ||
179 | rm -r /var/mariadb/backup | ||
180 | } | ||
181 | |||
182 | create_replication_user() | ||
183 | { | ||
184 | mariadb --skip-reconnect -t <<END | ||
185 | CREATE OR REPLACE USER '$2'@'$1' IDENTIFIED BY '$3'; | ||
186 | GRANT REPLICATION SLAVE ON *.* TO '$2'@'$1'; | ||
187 | END | ||
188 | } | ||
189 | |||
190 | showvars() | ||
191 | { | ||
192 | for h in "$@" | ||
193 | do | ||
194 | run_$h mariadb --skip-reconnect -t <<END | ||
195 | select VARIABLE_NAME,SESSION_VALUE,GLOBAL_VALUE | ||
196 | from INFORMATION_SCHEMA.SYSTEM_VARIABLES | ||
197 | where VARIABLE_NAME LIKE '%SLAVE%' \G | ||
198 | END | ||
199 | done | ||
200 | } | ||
201 | |||
202 | set -e | ||
203 | run_primary check_db | ||
204 | run_replica check_db | ||
205 | : showvars replica | ||
206 | : exit | ||
207 | |||
208 | run_primary create_replication_user \ | ||
209 | "$replica_host" \ | ||
210 | "$replication_user" \ | ||
211 | "$replication_password" | ||
212 | run_primary create_backup | ||
213 | run_primary send_backup "$replica_host" | ||
214 | run_replica restore_from_backup | ||
215 | run_replica enable_replication \ | ||
216 | "$primary_host" \ | ||
217 | "$replication_user" \ | ||
218 | "$replication_password" | ||
219 | run_replica check_db | ||
220 | run_primary delete_backup | ||
221 | run_primary check_db | ||