mysql_truck 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mysql_truck/dumper.rb +47 -48
- data/lib/mysql_truck/helper.rb +11 -4
- data/lib/mysql_truck/loader.rb +32 -21
- data/lib/mysql_truck/version.rb +1 -1
- metadata +4 -4
data/lib/mysql_truck/dumper.rb
CHANGED
@@ -27,27 +27,34 @@ module MysqlTruck
|
|
27
27
|
if dump_table?(table)
|
28
28
|
|
29
29
|
# This command creates a table_name.sql and a table_name.txt file
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
30
|
+
base_cmd = "mysqldump --quick"
|
31
|
+
|
32
|
+
# Dump schema
|
33
|
+
schema_cmd = "#{base_cmd} --no-data "
|
34
|
+
schema_cmd += "#{db_connection_options} #{table}"
|
35
|
+
schema_cmd += " > #{filename(table)[:schema_file]}"
|
36
|
+
puts schema_cmd
|
37
|
+
`#{schema_cmd}`
|
38
|
+
|
39
|
+
# Dump data
|
40
|
+
data_cmd = "#{base_cmd} --no-create-info "
|
41
|
+
data_cmd += "#{db_connection_options} #{table}"
|
42
|
+
data_cmd += " > #{filename(table)[:data_file]}"
|
43
|
+
puts data_cmd
|
44
|
+
`#{data_cmd}`
|
38
45
|
end
|
39
46
|
|
40
47
|
if split_schema_file?(table)
|
41
48
|
schema_contents = filename(table)[:schema_file].read
|
42
49
|
|
43
50
|
# Create schema with no indexes
|
44
|
-
File.open(filename(table)[:
|
51
|
+
File.open(filename(table)[:no_index_schema_file], 'w') do |f|
|
45
52
|
f.write(schema_contents.gsub(REGEX, ''))
|
46
53
|
end
|
47
54
|
|
48
55
|
# Create an alter table
|
49
56
|
indices = []
|
50
|
-
File.open(filename(table)[:
|
57
|
+
File.open(filename(table)[:alter_table_file], 'w') do |f|
|
51
58
|
f.write("ALTER TABLE #{table}\n")
|
52
59
|
|
53
60
|
schema_contents.gsub(/^,?\s*((UNIQUE)?\s*KEY\s`[A-Za-z\d_]+`\s*\([A-Za-z\d_,`]+\)),?\s*$/) do |part|
|
@@ -58,14 +65,14 @@ module MysqlTruck
|
|
58
65
|
end
|
59
66
|
|
60
67
|
if gzip_files?(table)
|
61
|
-
puts "gzipping #{filename(table)[:
|
62
|
-
`gzip #{filename(table)[:
|
68
|
+
puts "gzipping #{filename(table)[:no_index_schema_file]}."
|
69
|
+
`gzip #{filename(table)[:no_index_schema_file]}`
|
63
70
|
|
64
|
-
puts "gzipping #{filename(table)[:
|
65
|
-
`gzip #{filename(table)[:
|
71
|
+
puts "gzipping #{filename(table)[:alter_table_file]}."
|
72
|
+
`gzip #{filename(table)[:alter_table_file]}`
|
66
73
|
|
67
|
-
puts "gziping #{filename(table)[:
|
68
|
-
`gzip #{filename(table)[:
|
74
|
+
puts "gziping #{filename(table)[:data_file]}."
|
75
|
+
`gzip #{filename(table)[:data_file]}`
|
69
76
|
end
|
70
77
|
|
71
78
|
puts "#{table} dumped.\n\n"
|
@@ -105,28 +112,31 @@ module MysqlTruck
|
|
105
112
|
end
|
106
113
|
|
107
114
|
def bucket_path
|
108
|
-
@bucket_path ||= Pathname.new(bucket_dir).join(@time.strftime("%Y-%m-%d
|
115
|
+
@bucket_path ||= Pathname.new(bucket_dir).join(@time.strftime("%Y-%m-%d"))
|
109
116
|
end
|
110
117
|
|
111
118
|
def filename(table)
|
112
119
|
@table_filenames ||= {}
|
113
120
|
@table_filenames[table] ||= {
|
114
|
-
|
115
|
-
:
|
116
|
-
:
|
117
|
-
|
118
|
-
|
119
|
-
:
|
120
|
-
:
|
121
|
-
|
121
|
+
# mysqldump files
|
122
|
+
:schema_file => tmp_path.join("#{table}.schema.sql"),
|
123
|
+
:no_index_schema_file => tmp_path.join("#{table}.no_index.sql"),
|
124
|
+
|
125
|
+
# altered mysql dump files
|
126
|
+
:alter_table_file => tmp_path.join("#{table}.indices.sql"),
|
127
|
+
:data_file => tmp_path.join("#{table}.data.sql"),
|
128
|
+
|
129
|
+
# Gzip filenames
|
130
|
+
:gz_no_index_schema_file => tmp_path.join("#{table}.no_index.sql.gz"),
|
131
|
+
:gz_alter_table_file => tmp_path.join("#{table}.indices.sql.gz"),
|
132
|
+
:gz_data_file => tmp_path.join("#{table}.data.sql.gz"),
|
122
133
|
}
|
123
134
|
end
|
124
135
|
|
125
136
|
def gzip_files_exist?(table)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
tmp_path.join("#{table}.csv.gz")
|
137
|
+
filename(table)[:gz_no_index_schema_file].file? &&
|
138
|
+
filename(table)[:gz_alter_table_file].file? &&
|
139
|
+
filename(table)[:gz_data_file].file?
|
130
140
|
end
|
131
141
|
|
132
142
|
|
@@ -135,12 +145,7 @@ module MysqlTruck
|
|
135
145
|
(
|
136
146
|
smartly? &&
|
137
147
|
!filename(table)[:schema_file].exist? &&
|
138
|
-
!filename(table)[:
|
139
|
-
!filename(table)[:no_index_sql_file].exist? &&
|
140
|
-
!filename(table)[:index_sql_file].exist? &&
|
141
|
-
!filename(table)[:gz_no_index_sql_file].exist? &&
|
142
|
-
!filename(table)[:gz_index_sql_file].exist? &&
|
143
|
-
!filename(table)[:gz_csv_file].exist?
|
148
|
+
!filename(table)[:data_file].exist?
|
144
149
|
)
|
145
150
|
end
|
146
151
|
|
@@ -149,12 +154,9 @@ module MysqlTruck
|
|
149
154
|
(
|
150
155
|
smartly? &&
|
151
156
|
filename(table)[:schema_file].exist? &&
|
152
|
-
filename(table)[:
|
153
|
-
!filename(table)[:
|
154
|
-
!filename(table)[:
|
155
|
-
!filename(table)[:gz_no_index_sql_file].exist? &&
|
156
|
-
!filename(table)[:gz_index_sql_file].exist? &&
|
157
|
-
!filename(table)[:gz_csv_file].exist?
|
157
|
+
filename(table)[:data_file].exist? &&
|
158
|
+
!filename(table)[:no_index_schema_file].exist? &&
|
159
|
+
!filename(table)[:alter_table_file].exist?
|
158
160
|
)
|
159
161
|
end
|
160
162
|
|
@@ -162,13 +164,10 @@ module MysqlTruck
|
|
162
164
|
!smartly? ||
|
163
165
|
(
|
164
166
|
smartly? &&
|
165
|
-
filename(table)[:
|
166
|
-
filename(table)[:
|
167
|
-
filename(table)[:
|
168
|
-
|
169
|
-
!filename(table)[:gz_no_index_sql_file].exist? &&
|
170
|
-
!filename(table)[:gz_index_sql_file].exist? &&
|
171
|
-
!filename(table)[:gz_csv_file].exist?
|
167
|
+
filename(table)[:data_file].exist? &&
|
168
|
+
filename(table)[:no_index_schema_file].exist? &&
|
169
|
+
filename(table)[:alter_table_file].exist? &&
|
170
|
+
!gzip_files_exist?(table)
|
172
171
|
)
|
173
172
|
end
|
174
173
|
end # class Dumper
|
data/lib/mysql_truck/helper.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'benchmark'
|
1
2
|
module MysqlTruck
|
2
3
|
module Helper
|
3
4
|
include FileUtils
|
@@ -29,10 +30,6 @@ module MysqlTruck
|
|
29
30
|
!local_host?
|
30
31
|
end
|
31
32
|
|
32
|
-
def csv_options
|
33
|
-
" --fields-enclosed-by=\\\" --fields-terminated-by=, "
|
34
|
-
end
|
35
|
-
|
36
33
|
def initialize_directories
|
37
34
|
mkdir_p base_path
|
38
35
|
mkdir_p tmp_path
|
@@ -59,5 +56,15 @@ module MysqlTruck
|
|
59
56
|
def bucket_dir
|
60
57
|
"mysql/#{config[:bucket_dir] || config[:database]}/"
|
61
58
|
end
|
59
|
+
|
60
|
+
def benchmark
|
61
|
+
Benchmark.realtime do
|
62
|
+
yield
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def formatted_time(time)
|
67
|
+
"#{"%0.5f" % time}ms"
|
68
|
+
end
|
62
69
|
end
|
63
70
|
end
|
data/lib/mysql_truck/loader.rb
CHANGED
@@ -25,7 +25,7 @@ module MysqlTruck
|
|
25
25
|
@time = Time.new(*prefix.split("/").last.split("-"))
|
26
26
|
initialize_directories
|
27
27
|
|
28
|
-
puts "
|
28
|
+
puts "Download & gunzip backups"
|
29
29
|
puts "-------------------"
|
30
30
|
@bucket.keys(:prefix => prefix).each do |key|
|
31
31
|
puts "\n#{key}"
|
@@ -34,8 +34,8 @@ module MysqlTruck
|
|
34
34
|
# gunzip file
|
35
35
|
if tmp_path.join(filename).exist?
|
36
36
|
print " - Inflating #{filename} ... "
|
37
|
-
`gunzip -f #{tmp_path.join(filename)}`
|
38
|
-
print "complete.\n"
|
37
|
+
time = benchmark { `gunzip -f #{tmp_path.join(filename)}` }
|
38
|
+
print "complete (#{formatted_time time}).\n"
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -47,39 +47,48 @@ module MysqlTruck
|
|
47
47
|
else
|
48
48
|
import_cmd = "mysqlimport #{db_connection_options}"
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
|
+
files = Dir["#{tmp_path}/*.no_index.sql"]
|
52
|
+
total = files.size
|
53
|
+
count = 0
|
51
54
|
|
52
55
|
# Find all .no_index.sql files and process
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
+
files.sort.each do |file|
|
57
|
+
count += 1
|
58
|
+
table = File.basename(file, ".no_index.sql")
|
59
|
+
|
60
|
+
puts "\nProcessing #{table} (#{count}/#{total})"
|
56
61
|
|
57
62
|
schema_file = Pathname.new(file)
|
58
63
|
index_file = tmp_path.join("#{table}.indices.sql")
|
59
|
-
|
64
|
+
data_file = tmp_path.join("#{table}.data.sql")
|
60
65
|
|
61
66
|
|
62
67
|
print " - Loading schema for #{table} ... "
|
63
68
|
cmd = "cat #{schema_file} | mysql #{db_connection_options}"
|
64
|
-
`#{cmd}`
|
65
|
-
print "complete.\n"
|
69
|
+
time = benchmark { `#{cmd}` }
|
70
|
+
print "complete (#{formatted_time time}).\n"
|
66
71
|
|
67
|
-
if
|
72
|
+
if data_file.exist?
|
68
73
|
print " - Importing #{schema_file.basename(".sql")} ... "
|
69
|
-
|
70
|
-
|
74
|
+
time = benchmark do
|
75
|
+
`cat #{data_file} | mysql #{db_connection_options}`
|
76
|
+
end
|
77
|
+
print "complete (#{formatted_time time}).\n"
|
71
78
|
end
|
72
79
|
|
73
80
|
if index_file.exist?
|
74
81
|
print " - Adding indices for #{schema_file.basename(".no_index.sql")} ... "
|
75
82
|
cmd = "cat #{index_file} | mysql #{db_connection_options}"
|
76
|
-
|
77
|
-
|
83
|
+
time = benchmark do
|
84
|
+
`#{cmd}`
|
85
|
+
end
|
86
|
+
print "complete (#{formatted_time time}).\n"
|
78
87
|
end
|
79
88
|
|
80
89
|
schema_file.delete if schema_file.exist?
|
81
90
|
index_file.delete if index_file.exist?
|
82
|
-
|
91
|
+
data_file.delete if data_file.exist?
|
83
92
|
end
|
84
93
|
|
85
94
|
puts "Backup loaded."
|
@@ -106,13 +115,15 @@ module MysqlTruck
|
|
106
115
|
if !smartly? || (smartly? && !unzipped_file.exist?)
|
107
116
|
print " - Downloading... "
|
108
117
|
|
109
|
-
|
110
|
-
|
111
|
-
|
118
|
+
time = benchmark do
|
119
|
+
file.open("wb") do |f|
|
120
|
+
@bucket.s3.interface.get(@bucket.name, key.name) do |chunk|
|
121
|
+
f.write chunk
|
122
|
+
end
|
112
123
|
end
|
113
124
|
end
|
114
125
|
|
115
|
-
puts "complete."
|
126
|
+
puts "complete (#{formatted_time time})."
|
116
127
|
else
|
117
128
|
puts " already downloaded."
|
118
129
|
end
|
@@ -133,7 +144,7 @@ module MysqlTruck
|
|
133
144
|
return only_tables.include?(table_name)
|
134
145
|
end
|
135
146
|
|
136
|
-
if filename.match(/\.
|
147
|
+
if filename.match(/\.data\.sql\.gz$/)
|
137
148
|
is_data = true
|
138
149
|
is_schema = false
|
139
150
|
else
|
data/lib/mysql_truck/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql_truck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,11 +11,11 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-06-20 00:00:00.000000000Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: right_aws
|
18
|
-
requirement: &
|
18
|
+
requirement: &70141600570020 !ruby/object:Gem::Requirement
|
19
19
|
none: false
|
20
20
|
requirements:
|
21
21
|
- - ! '>='
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: '0'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
|
-
version_requirements: *
|
26
|
+
version_requirements: *70141600570020
|
27
27
|
description: Mysql database backup tool. Dumps/Loads to/from S3.
|
28
28
|
email:
|
29
29
|
- peter@paydrotalks.com
|