snapback 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -7
- data/README.md +6 -11
- data/bin/snapback +51 -67
- data/lib/snapback.rb +130 -0
- data/lib/snapback/cli/commit.rb +72 -0
- data/lib/snapback/cli/create.rb +157 -0
- data/lib/snapback/cli/drop.rb +94 -0
- data/lib/snapback/cli/install.rb +179 -0
- data/lib/snapback/cli/mount.rb +97 -0
- data/lib/snapback/cli/rollback.rb +161 -0
- data/lib/snapback/cli/snapshot.rb +155 -0
- data/lib/snapback/cli/unmount.rb +86 -0
- data/lib/snapback/configuration/Configuration_0_0_3.rb +99 -0
- data/lib/snapback/configuration_loader.rb +24 -0
- data/lib/snapback/filesystem.rb +39 -0
- data/lib/snapback/mysql/client_control.rb +125 -0
- data/lib/snapback/mysql/service_control.rb +14 -0
- data/lib/snapback/transaction.rb +25 -10
- data/lib/snapback/version.rb +3 -0
- metadata +110 -67
- data/lib/snapback/app/commit.rb +0 -35
- data/lib/snapback/app/create.rb +0 -117
- data/lib/snapback/app/drop.rb +0 -51
- data/lib/snapback/app/install.rb +0 -156
- data/lib/snapback/app/mount.rb +0 -62
- data/lib/snapback/app/rollback.rb +0 -63
- data/lib/snapback/app/snapshot.rb +0 -74
- data/lib/snapback/app/unmount.rb +0 -39
- data/lib/snapback/database.rb +0 -102
- data/lib/snapback/dsl.rb +0 -208
- data/lib/snapback/options.rb +0 -85
@@ -0,0 +1,94 @@
|
|
1
|
+
desc 'Drop an existing database'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :drop do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
help_now!('database(s) required') if args.empty?
|
6
|
+
|
7
|
+
# Load the configuration
|
8
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
9
|
+
|
10
|
+
# Connect to MySQL
|
11
|
+
mysql_client = config.mysql_client
|
12
|
+
|
13
|
+
args.each do |database|
|
14
|
+
|
15
|
+
# Start the transaction
|
16
|
+
Snapback::Transaction.new do
|
17
|
+
run_command "Selecting database: #{database}" do
|
18
|
+
mysql_client.database_select(database)
|
19
|
+
end
|
20
|
+
|
21
|
+
vg_name = config.lvm_volume_group
|
22
|
+
lv_name = "#{config.lvm_database_prefix}-#{database}"
|
23
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
24
|
+
|
25
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
26
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
27
|
+
|
28
|
+
# Drop tablespaces
|
29
|
+
tables = run_command "Getting list of tables in database" do
|
30
|
+
mysql_client.database_tables
|
31
|
+
end
|
32
|
+
|
33
|
+
tables.each do |table|
|
34
|
+
table = table.to_s
|
35
|
+
run_command "Changing table engine to MyISAM: #{table}" do
|
36
|
+
mysql_client.table_set_engine(table, "MyISAM")
|
37
|
+
end
|
38
|
+
|
39
|
+
run_command "Dropping table: #{table}" do
|
40
|
+
mysql_client.table_drop(table)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Flush
|
45
|
+
run_command "Flush tables with read lock" do
|
46
|
+
mysql_client.flush_tables
|
47
|
+
end
|
48
|
+
|
49
|
+
# Stop MySQL
|
50
|
+
run_command "Stop MySQL server" do
|
51
|
+
Snapback::MySQL::ServiceControl.stop
|
52
|
+
end
|
53
|
+
|
54
|
+
revert do
|
55
|
+
run_command "Start MySQL server" do
|
56
|
+
Snapback::MySQL::ServiceControl.start
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
run_command "Unlinking mysql data directory",
|
61
|
+
"unlink #{mysql_database_directory}"
|
62
|
+
|
63
|
+
revert do
|
64
|
+
run_command "Linking mysql data directory",
|
65
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Mount the new logical volume
|
69
|
+
run_command "Unmounting logical volume",
|
70
|
+
"umount #{mount_database_directory}"
|
71
|
+
|
72
|
+
revert do
|
73
|
+
run_command "Mounting logical volume",
|
74
|
+
"mount #{lv_path} #{mount_database_directory}"
|
75
|
+
end
|
76
|
+
|
77
|
+
# Remove logical volume
|
78
|
+
run_command "Remove logical volume",
|
79
|
+
"lvremove -f #{lv_path}"
|
80
|
+
|
81
|
+
# Start MySQL
|
82
|
+
run_command "Starting MySQL server" do
|
83
|
+
Snapback::MySQL::ServiceControl.start
|
84
|
+
end
|
85
|
+
|
86
|
+
revert do
|
87
|
+
run_command "Stopping MySQL server" do
|
88
|
+
Snapback::MySQL::ServiceControl.stop
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'lvm'
|
2
|
+
require 'snapback/configuration_loader'
|
3
|
+
|
4
|
+
desc 'Ensure the environment is setup'
|
5
|
+
command :install do |c|
|
6
|
+
c.action do |global_options,options,args|
|
7
|
+
help_now!('found arguments, none expected') if !args.empty?
|
8
|
+
|
9
|
+
Snapback::Transaction.new do
|
10
|
+
|
11
|
+
puts ""
|
12
|
+
puts "Hi!"
|
13
|
+
puts ""
|
14
|
+
puts "I'm going to guide you through setting up #{"snapback".colorize(:green)}. "
|
15
|
+
puts "This script will check to see if your environment can run "
|
16
|
+
puts "Snapback and will setup configuration files for you."
|
17
|
+
puts ""
|
18
|
+
|
19
|
+
run_command "Checking LVM is installed",
|
20
|
+
"lvm version"
|
21
|
+
|
22
|
+
lvm = nil
|
23
|
+
volume_groups = nil
|
24
|
+
|
25
|
+
# Get information from LVM
|
26
|
+
run_command "Retrieving volume group information" do
|
27
|
+
lvm = LVM::LVM.new({:command => "sudo lvm", :version => "2.02.30"})
|
28
|
+
volume_groups = lvm.volume_groups.to_a
|
29
|
+
|
30
|
+
if volume_groups.size == 0 then
|
31
|
+
raise "LVM is not setup: you do not have any volume groups"
|
32
|
+
end
|
33
|
+
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
puts ""
|
38
|
+
|
39
|
+
selected_volume_group = nil
|
40
|
+
|
41
|
+
# Decide which volume group to use
|
42
|
+
if volume_groups.size == 1 then
|
43
|
+
selected_volume_group = volume_groups[0];
|
44
|
+
puts "There is one volume group available"
|
45
|
+
else
|
46
|
+
puts "There are multiple volume groups available:"
|
47
|
+
|
48
|
+
volume_groups.each_with_index.map { |volume_group, index|
|
49
|
+
puts " #{index + 1}.\t#{volume_group.name.colorize(:yellow)}"
|
50
|
+
}
|
51
|
+
|
52
|
+
puts ""
|
53
|
+
|
54
|
+
volume_group_number = ask_int "Which volume group would you like Snapback use", volume_groups.size
|
55
|
+
selected_volume_group = volume_groups[volume_group_number - 1];
|
56
|
+
end
|
57
|
+
|
58
|
+
puts "Snapback will use the volume group #{selected_volume_group.name.colorize(:green)}"
|
59
|
+
puts ""
|
60
|
+
|
61
|
+
# Check for mount directory
|
62
|
+
mysql_mount_directory = ask_string "Where do you want to mount your logical volumes [/mnt/mysql]"
|
63
|
+
mysql_mount_directory = "/mnt/mysql" if mysql_mount_directory.empty?
|
64
|
+
|
65
|
+
run_command "Changing owner to mysql: #{mysql_mount_directory}",
|
66
|
+
"chown -R mysql:mysql #{mysql_mount_directory}"
|
67
|
+
|
68
|
+
has_mysql_mount_directory = run_command "Checking for directory #{mysql_mount_directory}" do
|
69
|
+
File.directory? mysql_mount_directory
|
70
|
+
end
|
71
|
+
|
72
|
+
if !has_mysql_mount_directory then
|
73
|
+
run_command "Creating directory #{mysql_mount_directory}",
|
74
|
+
"mkdir -p #{mysql_mount_directory}"
|
75
|
+
|
76
|
+
revert do
|
77
|
+
run_command "Removing directory #{mysql_mount_directory}",
|
78
|
+
"rm -rf #{mysql_mount_directory}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# MySQL connection
|
83
|
+
mysql_client = Snapback::MySQL::ClientControl.instance
|
84
|
+
|
85
|
+
while true
|
86
|
+
puts ""
|
87
|
+
puts "Enter the credentials to connect to MySQL on localhost"
|
88
|
+
|
89
|
+
mysql_client.hostname = "localhost"
|
90
|
+
|
91
|
+
# Ask for username
|
92
|
+
mysql_client.username = ask_string "MySQL username [root]"
|
93
|
+
mysql_client.username = "root" if mysql_client.username.empty?
|
94
|
+
|
95
|
+
# Ask for password
|
96
|
+
mysql_client.password = ask_string "MySQL password"
|
97
|
+
|
98
|
+
connected = run_command "Connecting to MySQL database" do
|
99
|
+
begin
|
100
|
+
mysql_client.connect
|
101
|
+
true
|
102
|
+
rescue
|
103
|
+
false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if connected then
|
108
|
+
break
|
109
|
+
else
|
110
|
+
next
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# MySQL properties
|
115
|
+
|
116
|
+
has_innodb_file_per_table = run_command "Checking innodb_file_per_table is activated" do
|
117
|
+
mysql_client.has_innodb_file_per_table?
|
118
|
+
end
|
119
|
+
|
120
|
+
if !has_innodb_file_per_table then
|
121
|
+
run_command "Setting innodb_file_per_table to ON" do
|
122
|
+
mysql_client.set_innodb_file_per_table true
|
123
|
+
end
|
124
|
+
|
125
|
+
revert do
|
126
|
+
run_command "Setting innodb_file_per_table to OFF" do
|
127
|
+
mysql_client.set_innodb_file_per_table false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
run_command "Writing configuration to file" do
|
133
|
+
config = {
|
134
|
+
'version' => Snapback::VERSION,
|
135
|
+
'lvm' => {
|
136
|
+
'volume_group' => "#{selected_volume_group.name}",
|
137
|
+
'database_prefix' => "snapback-database",
|
138
|
+
'snapshot_prefix' => "snapback-snapshot"
|
139
|
+
},
|
140
|
+
|
141
|
+
'mysql' => {
|
142
|
+
'hostname' => mysql_client.hostname,
|
143
|
+
'username' => mysql_client.username,
|
144
|
+
'password' => mysql_client.password
|
145
|
+
},
|
146
|
+
|
147
|
+
'filesystem' => {
|
148
|
+
'mount' => mysql_mount_directory
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
File.open(global_options[:config], 'w+') { |f| f.write(config.to_yaml) }
|
153
|
+
end
|
154
|
+
|
155
|
+
revert do
|
156
|
+
run_command "Removing configuration file" do
|
157
|
+
File.unlink global_options[:config]
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
puts ""
|
162
|
+
puts "Snapback has now been configured."
|
163
|
+
puts "To start using Snapback, run the following command: "
|
164
|
+
puts ""
|
165
|
+
puts "sudo snapback help".colorize(:yellow)
|
166
|
+
puts ""
|
167
|
+
puts "If your operating system uses AppArmor (e.g.: Ubuntu) you will need to "
|
168
|
+
puts "manually update your #{"/etc/apparmor.d/usr/sbin/mysqld".colorize(:green)} file "
|
169
|
+
puts "to include the following lines:"
|
170
|
+
puts "\t#{"/mnt/mysql/ rwk,".colorize(:green)}"
|
171
|
+
puts "\t#{"/mnt/mysql/** rwk,".colorize(:green)}"
|
172
|
+
puts ""
|
173
|
+
puts "Then manually restart AppArmor and MySQL using: "
|
174
|
+
puts "\t#{"service apparmor restart".colorize(:green)}"
|
175
|
+
puts "\t#{"service mysql restart".colorize(:green)}"
|
176
|
+
puts ""
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
desc 'Mount an existing database'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :mount do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
# Ensure all flags and switches are present
|
6
|
+
help_now!('database(s) required') if args.empty?
|
7
|
+
|
8
|
+
# Load the configuration
|
9
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
10
|
+
|
11
|
+
# Connect to MySQL
|
12
|
+
mysql_client = config.mysql_client
|
13
|
+
|
14
|
+
# For each database
|
15
|
+
args.each do |database|
|
16
|
+
|
17
|
+
# Start the transaction
|
18
|
+
Snapback::Transaction.new do
|
19
|
+
run_command "Selecting database: #{database}" do
|
20
|
+
mysql_client.database_select(database)
|
21
|
+
end
|
22
|
+
|
23
|
+
vg_name = config.lvm_volume_group
|
24
|
+
lv_name = config.lvm_logical_database database
|
25
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
26
|
+
|
27
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
28
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
29
|
+
|
30
|
+
lv_exists = run_command "Checking logical volume exists" do
|
31
|
+
File.exists?(lv_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
if !lv_exists then
|
35
|
+
raise "Logical volume #{lv_path.colorize(:red)} does not exist"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Flush
|
39
|
+
run_command "Flush tables with read lock" do
|
40
|
+
mysql_client.flush_tables
|
41
|
+
end
|
42
|
+
|
43
|
+
# Stop MySQL
|
44
|
+
run_command "Stop MySQL server" do
|
45
|
+
Snapback::MySQL::ServiceControl.stop
|
46
|
+
end
|
47
|
+
|
48
|
+
revert do
|
49
|
+
run_command "Start MySQL server" do
|
50
|
+
Snapback::MySQL::ServiceControl.start
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
directory_exists = run_command "Checking if mount directory exists" do
|
55
|
+
File.directory? mount_database_directory
|
56
|
+
end
|
57
|
+
|
58
|
+
# Check mount directory exists
|
59
|
+
if !directory_exists then
|
60
|
+
run_command "Creating mount directory",
|
61
|
+
"mkdir #{mount_database_directory}"
|
62
|
+
|
63
|
+
revert do
|
64
|
+
run_command "Removing mount directory",
|
65
|
+
"rmdir #{$mount_database_directory}"
|
66
|
+
end
|
67
|
+
|
68
|
+
run_command "Changing permissions of mount directory",
|
69
|
+
"chmod 0777 #{mount_database_directory}"
|
70
|
+
end
|
71
|
+
|
72
|
+
run_command "Mounting directory",
|
73
|
+
"mount #{lv_path} #{mount_database_directory}"
|
74
|
+
|
75
|
+
run_command "Linking mount directory",
|
76
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
77
|
+
|
78
|
+
run_command "Changing ownership of: #{mount_database_directory}",
|
79
|
+
"chown -R mysql:mysql #{mount_database_directory}"
|
80
|
+
|
81
|
+
run_command "Changing ownership of: #{mysql_database_directory}",
|
82
|
+
"chown -R mysql:mysql #{mysql_database_directory}"
|
83
|
+
|
84
|
+
# Start MySQL
|
85
|
+
run_command "Start MySQL server" do
|
86
|
+
Snapback::MySQL::ServiceControl.start
|
87
|
+
end
|
88
|
+
|
89
|
+
revert do
|
90
|
+
run_command "Stop MySQL server" do
|
91
|
+
Snapback::MySQL::ServiceControl.stop
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
desc 'Rollback the working copy to the snapshot'
|
2
|
+
arg_name 'database [, ...]'
|
3
|
+
command :rollback do |c|
|
4
|
+
c.action do |global_options,options,args|
|
5
|
+
help_now!('database(s) required') if args.empty?
|
6
|
+
|
7
|
+
# Load the configuration
|
8
|
+
config = Snapback::ConfigurationLoader.factory global_options[:config]
|
9
|
+
|
10
|
+
# Connect to MySQL
|
11
|
+
mysql_client = config.mysql_client
|
12
|
+
|
13
|
+
args.each do |database|
|
14
|
+
|
15
|
+
# Start the transaction
|
16
|
+
Snapback::Transaction.new do
|
17
|
+
|
18
|
+
run_command "Selecting database: #{database}" do
|
19
|
+
mysql_client.database_select(database)
|
20
|
+
end
|
21
|
+
|
22
|
+
vg_name = config.lvm_volume_group
|
23
|
+
lv_name = "#{config.lvm_database_prefix}-#{database}"
|
24
|
+
lv_path = "/dev/#{vg_name}/#{lv_name}"
|
25
|
+
|
26
|
+
mount_database_directory = config.filesystem_mount_directory(database)
|
27
|
+
mysql_database_directory = "#{mysql_client.get_data_directory}/#{database}"
|
28
|
+
|
29
|
+
# Drop tablespaces
|
30
|
+
tables = run_command "Getting list of tables in database" do
|
31
|
+
mysql_client.database_tables
|
32
|
+
end
|
33
|
+
|
34
|
+
tables.each do |table|
|
35
|
+
table = table.to_s
|
36
|
+
run_command "Changing table engine to MyISAM: #{table}" do
|
37
|
+
mysql_client.table_set_engine(table, "MyISAM")
|
38
|
+
end
|
39
|
+
|
40
|
+
run_command "Dropping table: #{table}" do
|
41
|
+
mysql_client.table_drop(table)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Flush
|
46
|
+
run_command "Flush tables with read lock" do
|
47
|
+
mysql_client.flush_tables
|
48
|
+
end
|
49
|
+
|
50
|
+
# Stop MySQL
|
51
|
+
run_command "Stop MySQL server" do
|
52
|
+
Snapback::MySQL::ServiceControl.stop
|
53
|
+
end
|
54
|
+
|
55
|
+
revert do
|
56
|
+
run_command "Start MySQL server" do
|
57
|
+
Snapback::MySQL::ServiceControl.start
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Unlink
|
62
|
+
run_command "Unlinking mysql data directory",
|
63
|
+
"unlink #{mysql_database_directory}"
|
64
|
+
|
65
|
+
revert do
|
66
|
+
run_command "Linking mysql data directory",
|
67
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Unmount
|
71
|
+
run_command "Unmounting logical volume",
|
72
|
+
"umount #{mount_database_directory}"
|
73
|
+
|
74
|
+
revert do
|
75
|
+
run_command "Mounting logical volume",
|
76
|
+
"mount #{lv_path} #{mount_database_directory}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Deactivate
|
80
|
+
run_command "De-activating logical volume",
|
81
|
+
"lvchange -an #{lv_path}"
|
82
|
+
|
83
|
+
revert do
|
84
|
+
run_command "Re-activating logical volume",
|
85
|
+
"lvchange -ay #{lv_path}"
|
86
|
+
end
|
87
|
+
|
88
|
+
# Merge the old logical volume into the new one
|
89
|
+
# lvconvert --merge /dev/{vgName}/backup-{dbName}
|
90
|
+
run_command "Rolling back to the snapshot",
|
91
|
+
"lvconvert --merge /dev/#{vg_name}/#{config.lvm_snapshot_prefix}-#{database}"
|
92
|
+
|
93
|
+
# Active the master drive
|
94
|
+
run_command "Activating logical volume",
|
95
|
+
"lvchange -ay #{lv_path}"
|
96
|
+
|
97
|
+
revert do
|
98
|
+
run_command "Deactivating logical volume",
|
99
|
+
"lvchange -an #{lv_path}"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Mount the master drive
|
103
|
+
run_command "Mounting logical volume",
|
104
|
+
"mount #{lv_path} #{mount_database_directory}"
|
105
|
+
|
106
|
+
revert do
|
107
|
+
run_command "Unmounting logical volume",
|
108
|
+
"umount #{mount_database_directory}"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Symbolic-link the MySQL data directory to the new logical volume
|
112
|
+
run_command "Linking mysql data directory",
|
113
|
+
"ln -s #{mount_database_directory} #{mysql_database_directory}"
|
114
|
+
|
115
|
+
revert do
|
116
|
+
run_command "Unlinking mysql data directory",
|
117
|
+
"unlink #{mysql_database_directory}"
|
118
|
+
end
|
119
|
+
|
120
|
+
# Change the permissions & ownership to MySQL
|
121
|
+
run_command "Changing owner to mysql: #{mysql_database_directory}",
|
122
|
+
"chown -R mysql:mysql #{mysql_database_directory}"
|
123
|
+
|
124
|
+
run_command "Changing owner to mysql: #{mount_database_directory}",
|
125
|
+
"chown -R mysql:mysql #{mount_database_directory}"
|
126
|
+
|
127
|
+
# Start MySQL
|
128
|
+
run_command "Starting MySQL server" do
|
129
|
+
Snapback::MySQL::ServiceControl.start
|
130
|
+
end
|
131
|
+
|
132
|
+
revert do
|
133
|
+
run_command "Stopping MySQL server" do
|
134
|
+
Snapback::MySQL::ServiceControl.stop
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# Reconnect
|
139
|
+
run_command "Re-connecting to MySQL" do
|
140
|
+
mysql_client.connect
|
141
|
+
end
|
142
|
+
|
143
|
+
run_command "Re-selecting database: #{database}" do
|
144
|
+
mysql_client.database_select(database)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Import tablespaces and optimize table
|
148
|
+
tables = run_command "Getting list of tables in database" do
|
149
|
+
mysql_client.database_tables
|
150
|
+
end
|
151
|
+
|
152
|
+
tables.each do |table|
|
153
|
+
table = table.to_s
|
154
|
+
run_command "Optimizing table: #{table}" do
|
155
|
+
mysql_client.table_optimize(table)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|