mysql_manager 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7db617b7015f5a675990bef408681d12e9333c1e
4
+ data.tar.gz: 6c130b35e26811fd5defcdfba76efb38147aef0f
5
+ SHA512:
6
+ metadata.gz: ee25ebbb9fc2c754fb96b5edbe9ef157e6483be8954ab928ba008a77f1491686e1e523d9fb1afa2dbae7bb18df5cb6855115e2487f782f6dc068151db7a5eaa3
7
+ data.tar.gz: cb8de0cc6774c0762e963ccbd92fa2709e8d4c13c8a4528455992299e4c11ea853aad089eb4f4a74f677ef4b32ed99bcc5612392a7ea0ea4d30a343440832ae2
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- Usage: mysql-manager options
25
+ Usage: bin/mysql-manager options
26
26
  --kill Kill queries based on specified criteria
27
27
  --kill:max-query-time TIME Kill queries that have been running for more than TIME
28
28
  --kill:user USER Kill queries matching USER (repeatable)
@@ -48,10 +48,17 @@ Or install it yourself as:
48
48
  --log:file FILE Write logs to FILE (default: STDERR)
49
49
  --log:age DAYS Rotate logs after DAYS pass (default: 7)
50
50
  --log:size SIZE Rotate logs after the grow past SIZE bytes
51
+ --hotcopy Perform a hotcopy
52
+ --hotcopy:data-dir PATH Rsync mysql data dir from PATH (default: /var/lib/mysql)
53
+ --hotcopy:backup-dir PATH Rsync to PATH (default: /tmp/mysql)
54
+ --hotcopy:rsync-args ARGS Arguments to pass to rsync (default: -av)
55
+ --hotcopy:rsync-bin bin Rsync executable path (default: rsync)
56
+ --hotcopy:rsync-ttl ttl Acceptable rsync execution time before performing table locks (default: 60)
51
57
  --dry-run Do not run statements which affect the state of the database when executed
52
58
  -V, --version Display version information
53
59
  -h, --help Display this screen
54
60
 
61
+
55
62
  ## How matching is done
56
63
 
57
64
  If you specify a simple string as a parameter (e.g. `--kill:user api`), this is interpreted as an exactly matching
@@ -78,6 +85,16 @@ Reload `/etc/my.cnf` without restarting MySQL:
78
85
 
79
86
  mysql-manager --reload-my-cnf --reload-my-cnf:config /etc/my.cnf --log:level DEBUG
80
87
 
88
+ Perform a hotcopy backup of the running mysql database using rsync to a remote server. It will repeated rsync the folder without locks until syncs take less than 30 seconds.
89
+
90
+ mysql-manager --hotcopy \
91
+ --hotcopy:data-dir /var/lib/mysql/ \
92
+ --hotcopy:backup-dir user@remote.host.com:/tmp/mysql/ \
93
+ --hotcopy:rsync-args "-av --exclude=*.err" \
94
+ --hotcopy:rsync-ttl 30 \
95
+ --db:user root \
96
+ --db:pass $MYSQL_ROOT_PASSWORD
97
+
81
98
  ## Contributors
82
99
 
83
100
  https://github.com/osterman/mysql_manager/graphs/contributors
@@ -40,6 +40,7 @@ module MysqlManager
40
40
  @options[:kill] = {}
41
41
  @options[:reload_my_cnf] = {}
42
42
  @options[:skip_replication_errors] = {}
43
+ @options[:hotcopy] = {}
43
44
 
44
45
  begin
45
46
  @optparse = OptionParser.new do |opts|
@@ -178,6 +179,40 @@ module MysqlManager
178
179
  @options[:log][:size] = size.to_i
179
180
  end
180
181
 
182
+ #
183
+ # Hotcopy
184
+ #
185
+
186
+ @options[:hotcopy][:execute] = false
187
+ opts.on( '--hotcopy', 'Perform a hotcopy') do
188
+ @options[:hotcopy][:execute] = true
189
+ end
190
+
191
+ @options[:hotcopy][:data_dir] = '/var/lib/mysql'
192
+ opts.on( '--hotcopy:data-dir PATH', "Rsync mysql data dir from PATH (default: #{@options[:hotcopy][:data_dir]})") do |path|
193
+ @options[:hotcopy][:data_dir] = path.to_s
194
+ end
195
+
196
+ @options[:hotcopy][:backup_dir] = '/tmp/mysql'
197
+ opts.on( '--hotcopy:backup-dir PATH', "Rsync to PATH (default: #{@options[:hotcopy][:backup_dir]})") do |path|
198
+ @options[:hotcopy][:backup_dir] = path.to_s
199
+ end
200
+
201
+ @options[:hotcopy][:rsync_args] = '-av'
202
+ opts.on( '--hotcopy:rsync-args ARGS', "Arguments to pass to rsync (default: #{@options[:hotcopy][:rsync_args]})") do |args|
203
+ @options[:hotcopy][:rsync_args] = Shellwords.split(args.to_s)
204
+ end
205
+
206
+ @options[:hotcopy][:rsync_bin] = 'rsync'
207
+ opts.on( '--hotcopy:rsync-bin bin', "Rsync executable path (default: #{@options[:hotcopy][:rsync_bin]})") do |bin|
208
+ @options[:hotcopy][:rsync_bin] = bin.to_s
209
+ end
210
+
211
+ @options[:hotcopy][:rsync_ttl] = 60
212
+ opts.on( '--hotcopy:rsync-ttl ttl', "Acceptable rsync execution time before performing table locks (default: #{@options[:hotcopy][:rsync_ttl]})") do |ttl|
213
+ @options[:hotcopy][:rsync_ttl] = ttl.to_i
214
+ end
215
+
181
216
  #
182
217
  # General options
183
218
  #
@@ -234,6 +269,9 @@ module MysqlManager
234
269
  when :reload_my_cnf
235
270
  @log.debug("about to call reload_my_cnf")
236
271
  @utilities.reload_my_cnf(options)
272
+ when :hotcopy
273
+ @log.debug("about to call hotcopy")
274
+ @utilities.hotcopy(options)
237
275
  end
238
276
  rescue DBI::DatabaseError => e
239
277
  @log.fatal(e.message)
@@ -20,6 +20,8 @@
20
20
  require 'dbi'
21
21
  require 'logger'
22
22
  require 'parseconfig'
23
+ require 'shellwords'
24
+ require 'open3'
23
25
 
24
26
  module MysqlManager
25
27
  class FileNotFoundException < Exception; end
@@ -214,5 +216,72 @@ module MysqlManager
214
216
  @log.error("Error code: #{e.err}: #{e.errstr}")
215
217
  end
216
218
  end
219
+
220
+ def run(cmd)
221
+ stdout, stderr, status = Open3.capture3(Shellwords.join(cmd))
222
+ if status != 0
223
+ puts stderr
224
+ raise Exception.new("execution of command failed")
225
+ end
226
+ return status
227
+ end
228
+
229
+ def hotcopy(options = {})
230
+ begin
231
+ t_start = Time.now.to_f
232
+ # ensure mysql directory exists
233
+ unless File.directory?(options[:data_dir])
234
+ raise FileNotFoundException.new("Unable to open mysql data dir #{options[:data_dir]}")
235
+ end
236
+
237
+ rsync = []
238
+ rsync << options[:rsync_bin]
239
+ rsync << options[:rsync_args]
240
+ rsync << options[:data_dir] + '/'
241
+ rsync << options[:backup_dir] + '/'
242
+
243
+ # create target directory if it does not already exist
244
+ unless File.directory?(options[:backup_dir])
245
+ @log.info("Creating #{options[:backup_dir]}")
246
+ run ['mkdir', '-p', options[:backup_dir]]
247
+ end
248
+
249
+ rsync.flatten!
250
+
251
+ t_rsync = Time.now.to_f
252
+ t_rsync_elapsed = Time.now.to_f
253
+ while t_rsync_elapsed > options[:rsync_ttl]
254
+ # first do a raw rsync without table locks
255
+ @log.info("Performing first-pass rsync without table locks")
256
+ run rsync
257
+ t_rsync_elapsed = Time.now.to_f - t_rsync
258
+ @log.info("Rsync took #{t_rsync_elapsed} seconds")
259
+ sleep 1
260
+ t_rsync = Time.now.to_f
261
+ end
262
+
263
+ # then flush tables with read lock
264
+ @log.info("Locking tables")
265
+ t_lock = Time.now.to_f
266
+ @dbh.do("FLUSH TABLES WITH READ LOCK") unless @dry_run
267
+
268
+ # re-sync the delats
269
+ @log.info("Performing second-pass rsync with table locks")
270
+ run rsync
271
+
272
+ # release locks
273
+ @log.info("Unlocking tables")
274
+ @dbh.do('UNLOCK TABLES')
275
+ @log.info("Total lock time #{Time.now.to_f - t_lock} seconds")
276
+ @log.info("Total elapsed time #{Time.now.to_f - t_start} seconds")
277
+
278
+ rescue DBI::DatabaseError => e
279
+ @log.debug(@dbh.last_statement)
280
+ @log.warn(e.message)
281
+ end
282
+ end
283
+
284
+
285
+
217
286
  end
218
287
  end
@@ -18,5 +18,5 @@
18
18
  # along with MySQL Manager. If not, see <http://www.gnu.org/licenses/>.
19
19
  #
20
20
  module MysqlManager
21
- VERSION = "1.0.3"
21
+ VERSION = "1.0.4"
22
22
  end
@@ -16,6 +16,7 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = MysqlManager::VERSION
18
18
  gem.add_runtime_dependency "parseconfig", ">= 1.0.2"
19
+ gem.add_runtime_dependency "mysql2", ">= 0.3.18"
19
20
  gem.add_runtime_dependency "dbi", ">= 0.4.5"
20
21
  gem.add_runtime_dependency "dbd-mysql", ">= 0.4.4"
21
22
  end
metadata CHANGED
@@ -1,77 +1,79 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mysql_manager
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 1
7
- - 0
8
- - 3
9
- version: 1.0.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Erik Osterman
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2012-08-09 00:00:00 -07:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2015-05-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: parseconfig
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.2
20
+ type: :runtime
22
21
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 0
31
- - 2
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
32
26
  version: 1.0.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: mysql2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.18
33
34
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: dbi
37
35
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
39
- none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 0
45
- - 4
46
- - 5
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.18
41
+ - !ruby/object:Gem::Dependency
42
+ name: dbi
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
47
  version: 0.4.5
48
48
  type: :runtime
49
- version_requirements: *id002
50
- - !ruby/object:Gem::Dependency
51
- name: dbd-mysql
52
49
  prerelease: false
53
- requirement: &id003 !ruby/object:Gem::Requirement
54
- none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- segments:
59
- - 0
60
- - 4
61
- - 4
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.4.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: dbd-mysql
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
62
61
  version: 0.4.4
63
62
  type: :runtime
64
- version_requirements: *id003
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.4.4
65
69
  description: MySQL Manager is a utility to perform routine tasks on a MySQL database.
66
- email:
70
+ email:
67
71
  - e@osterman.com
68
- executables:
72
+ executables:
69
73
  - mysql-manager
70
74
  extensions: []
71
-
72
75
  extra_rdoc_files: []
73
-
74
- files:
76
+ files:
75
77
  - .gitignore
76
78
  - Gemfile
77
79
  - LICENSE
@@ -83,37 +85,30 @@ files:
83
85
  - lib/mysql_manager/utilities.rb
84
86
  - lib/mysql_manager/version.rb
85
87
  - mysql_manager.gemspec
86
- has_rdoc: true
87
88
  homepage: https://github.com/osterman/mysql_manager
88
- licenses:
89
+ licenses:
89
90
  - GPL3
91
+ metadata: {}
90
92
  post_install_message:
91
93
  rdoc_options: []
92
-
93
- require_paths:
94
+ require_paths:
94
95
  - lib
95
- required_ruby_version: !ruby/object:Gem::Requirement
96
- none: false
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- segments:
101
- - 0
102
- version: "0"
103
- required_rubygems_version: !ruby/object:Gem::Requirement
104
- none: false
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- segments:
109
- - 0
110
- version: "0"
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
111
106
  requirements: []
112
-
113
107
  rubyforge_project:
114
- rubygems_version: 1.3.7
108
+ rubygems_version: 2.0.14
115
109
  signing_key:
116
- specification_version: 3
117
- summary: MySQL Manager is a utility to perform routine tasks such as restoring replication after errors, killing queries based on a set of criteria, or reloading my.cnf without restarting the database.
110
+ specification_version: 4
111
+ summary: MySQL Manager is a utility to perform routine tasks such as restoring replication
112
+ after errors, killing queries based on a set of criteria, or reloading my.cnf without
113
+ restarting the database.
118
114
  test_files: []
119
-