innodb_ruby 0.9.14 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +5 -6
- data/bin/innodb_log +13 -18
- data/bin/innodb_space +654 -778
- data/lib/innodb/checksum.rb +26 -24
- data/lib/innodb/data_dictionary.rb +490 -550
- data/lib/innodb/data_type.rb +362 -325
- data/lib/innodb/field.rb +102 -89
- data/lib/innodb/fseg_entry.rb +22 -26
- data/lib/innodb/history.rb +21 -21
- data/lib/innodb/history_list.rb +72 -76
- data/lib/innodb/ibuf_bitmap.rb +36 -36
- data/lib/innodb/ibuf_index.rb +6 -2
- data/lib/innodb/index.rb +245 -276
- data/lib/innodb/inode.rb +166 -124
- data/lib/innodb/list.rb +196 -183
- data/lib/innodb/log.rb +139 -110
- data/lib/innodb/log_block.rb +100 -91
- data/lib/innodb/log_group.rb +53 -64
- data/lib/innodb/log_reader.rb +97 -96
- data/lib/innodb/log_record.rb +328 -279
- data/lib/innodb/lsn.rb +86 -81
- data/lib/innodb/page/blob.rb +82 -83
- data/lib/innodb/page/fsp_hdr_xdes.rb +174 -165
- data/lib/innodb/page/ibuf_bitmap.rb +34 -34
- data/lib/innodb/page/index.rb +965 -924
- data/lib/innodb/page/index_compressed.rb +34 -34
- data/lib/innodb/page/inode.rb +103 -112
- data/lib/innodb/page/sys.rb +13 -15
- data/lib/innodb/page/sys_data_dictionary_header.rb +81 -59
- data/lib/innodb/page/sys_ibuf_header.rb +45 -42
- data/lib/innodb/page/sys_rseg_header.rb +88 -82
- data/lib/innodb/page/trx_sys.rb +204 -182
- data/lib/innodb/page/undo_log.rb +106 -92
- data/lib/innodb/page.rb +417 -414
- data/lib/innodb/record.rb +121 -164
- data/lib/innodb/record_describer.rb +66 -68
- data/lib/innodb/space.rb +381 -413
- data/lib/innodb/stats.rb +33 -35
- data/lib/innodb/system.rb +149 -171
- data/lib/innodb/undo_log.rb +129 -107
- data/lib/innodb/undo_record.rb +255 -247
- data/lib/innodb/util/buffer_cursor.rb +81 -79
- data/lib/innodb/util/read_bits_at_offset.rb +2 -1
- data/lib/innodb/version.rb +2 -2
- data/lib/innodb/xdes.rb +144 -142
- data/lib/innodb.rb +4 -5
- metadata +100 -25
data/lib/innodb/stats.rb
CHANGED
@@ -1,46 +1,44 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Collect stats globally within innodb_ruby for comparison purposes and for
|
4
4
|
# correctness checking.
|
5
|
-
|
6
|
-
|
5
|
+
module Innodb
|
6
|
+
class Stats
|
7
|
+
@data = Hash.new(0)
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
# Increment a statistic by name (typically a symbol), optionally by a value
|
14
|
-
# provided.
|
15
|
-
def self.increment(name, value=1)
|
16
|
-
@@data[name] += value
|
17
|
-
end
|
9
|
+
class << self
|
10
|
+
attr_reader :data
|
11
|
+
end
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
# Increment a statistic by name (typically a symbol), optionally by a value
|
14
|
+
# provided.
|
15
|
+
def self.increment(name, value = 1)
|
16
|
+
@data[name] += value
|
17
|
+
end
|
23
18
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
19
|
+
# Get a statistic by name.
|
20
|
+
def self.get(name)
|
21
|
+
@data[name]
|
22
|
+
end
|
29
23
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"Statistic",
|
35
|
-
"Count",
|
36
|
-
]
|
37
|
-
@@data.sort.each do |name, count|
|
38
|
-
io.puts "%-50s%10i" % [
|
39
|
-
name,
|
40
|
-
count
|
41
|
-
]
|
24
|
+
# Reset all statistics.
|
25
|
+
def self.reset
|
26
|
+
@data.clear
|
27
|
+
nil
|
42
28
|
end
|
43
29
|
|
44
|
-
|
30
|
+
# Print a simple report of collected statistics, optionally to the IO object
|
31
|
+
# provided, or by default to STDOUT.
|
32
|
+
def self.print_report(io = $stdout)
|
33
|
+
io.puts "%-50s%10s" % %w[Statistic Count]
|
34
|
+
@data.sort.each do |name, count|
|
35
|
+
io.puts "%-50s%10i" % [
|
36
|
+
name,
|
37
|
+
count,
|
38
|
+
]
|
39
|
+
end
|
40
|
+
|
41
|
+
nil
|
42
|
+
end
|
45
43
|
end
|
46
44
|
end
|
data/lib/innodb/system.rb
CHANGED
@@ -1,230 +1,208 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# A class representing an entire InnoDB system, having a system tablespace
|
4
4
|
# and any number of attached single-table tablespaces.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# A hash of spaces by space ID.
|
10
|
-
attr_reader :spaces
|
11
|
-
|
12
|
-
# Array of space names for which a space file was not found.
|
13
|
-
attr_reader :orphans
|
14
|
-
|
15
|
-
# The Innodb::DataDictionary for this system.
|
16
|
-
attr_reader :data_dictionary
|
17
|
-
|
18
|
-
# The space ID of the system space, always 0.
|
19
|
-
SYSTEM_SPACE_ID = 0
|
20
|
-
|
21
|
-
def initialize(arg)
|
22
|
-
if arg.is_a?(Array) && arg.size > 1
|
23
|
-
data_filenames = arg
|
24
|
-
else
|
25
|
-
arg = arg.first if arg.is_a?(Array)
|
26
|
-
if File.directory?(arg)
|
27
|
-
data_filenames = Dir.glob(arg + "/ibdata?").sort
|
28
|
-
if data_filenames.empty?
|
29
|
-
raise "Couldn't find any ibdata files in #{arg}"
|
30
|
-
end
|
31
|
-
else
|
32
|
-
data_filenames = [arg]
|
33
|
-
end
|
34
|
-
end
|
5
|
+
module Innodb
|
6
|
+
class System
|
7
|
+
# A hash of configuration options by configuration key.
|
8
|
+
attr_reader :config
|
35
9
|
|
36
|
-
|
37
|
-
|
38
|
-
@config = {
|
39
|
-
:datadir => File.dirname(data_filenames.first),
|
40
|
-
}
|
10
|
+
# A hash of spaces by space ID.
|
11
|
+
attr_reader :spaces
|
41
12
|
|
42
|
-
|
13
|
+
# Array of space names for which a space file was not found.
|
14
|
+
attr_reader :orphans
|
43
15
|
|
44
|
-
|
45
|
-
|
16
|
+
# The Innodb::DataDictionary for this system.
|
17
|
+
attr_reader :data_dictionary
|
46
18
|
|
47
|
-
|
48
|
-
|
49
|
-
spaces[SYSTEM_SPACE_ID]
|
50
|
-
end
|
19
|
+
# The space ID of the system space, always 0.
|
20
|
+
SYSTEM_SPACE_ID = 0
|
51
21
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
22
|
+
def initialize(arg, data_directory: nil)
|
23
|
+
if arg.is_a?(Array) && arg.size > 1
|
24
|
+
data_filenames = arg
|
25
|
+
else
|
26
|
+
arg = arg.first if arg.is_a?(Array)
|
27
|
+
if File.directory?(arg)
|
28
|
+
data_filenames = Dir.glob("#{arg}/ibdata?").sort
|
29
|
+
raise "Couldn't find any ibdata files in #{arg}" if data_filenames.empty?
|
30
|
+
else
|
31
|
+
data_filenames = [arg]
|
32
|
+
end
|
33
|
+
end
|
57
34
|
|
58
|
-
|
59
|
-
|
35
|
+
@spaces = {}
|
36
|
+
@orphans = []
|
37
|
+
@config = {
|
38
|
+
data_directory: data_directory || File.dirname(data_filenames.first),
|
39
|
+
}
|
60
40
|
|
61
|
-
|
62
|
-
def add_space_file(space_filenames)
|
63
|
-
space = Innodb::Space.new(space_filenames)
|
64
|
-
space.innodb_system = self
|
65
|
-
add_space(space)
|
66
|
-
end
|
41
|
+
add_space_file(data_filenames)
|
67
42
|
|
68
|
-
|
69
|
-
|
70
|
-
orphans << space_file
|
71
|
-
end
|
43
|
+
@data_dictionary = Innodb::DataDictionary.new(system_space)
|
44
|
+
end
|
72
45
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
space_file = "%s/%s.ibd" % [config[:datadir], table_name]
|
77
|
-
if File.exist?(space_file)
|
78
|
-
add_space_file(space_file)
|
79
|
-
else
|
80
|
-
add_space_orphan(table_name)
|
46
|
+
# A helper to get the system space.
|
47
|
+
def system_space
|
48
|
+
spaces[SYSTEM_SPACE_ID]
|
81
49
|
end
|
82
|
-
end
|
83
50
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
return spaces[space_id] if spaces[space_id]
|
51
|
+
# Add an already-constructed Innodb::Space object.
|
52
|
+
def add_space(space)
|
53
|
+
raise "Object was not an Innodb::Space" unless space.is_a?(Innodb::Space)
|
88
54
|
|
89
|
-
|
90
|
-
raise "Table with space ID #{space_id} not found"
|
55
|
+
spaces[space.space_id.to_i] = space
|
91
56
|
end
|
92
57
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
58
|
+
# Add a space by filename.
|
59
|
+
def add_space_file(space_filenames)
|
60
|
+
space = Innodb::Space.new(space_filenames)
|
61
|
+
space.innodb_system = self
|
62
|
+
add_space(space)
|
63
|
+
end
|
97
64
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
raise "Table #{table_name} not found"
|
65
|
+
# Add an orphaned space.
|
66
|
+
def add_space_orphan(space_file)
|
67
|
+
orphans << space_file
|
102
68
|
end
|
103
69
|
|
104
|
-
|
105
|
-
|
70
|
+
# Add a space by table name, constructing an appropriate filename
|
71
|
+
# from the provided table name.
|
72
|
+
def add_table(table_name)
|
73
|
+
space_file = "%s/%s.ibd" % [config[:data_directory], table_name]
|
74
|
+
if File.exist?(space_file)
|
75
|
+
add_space_file(space_file)
|
76
|
+
else
|
77
|
+
add_space_orphan(table_name)
|
78
|
+
end
|
106
79
|
end
|
107
80
|
|
108
|
-
space
|
109
|
-
|
81
|
+
# Return an Innodb::Space object for a given space ID, looking up
|
82
|
+
# and adding the single-table space if necessary.
|
83
|
+
def space(space_id)
|
84
|
+
return spaces[space_id] if spaces[space_id]
|
110
85
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
86
|
+
unless (table_record = data_dictionary.table_by_space_id(space_id))
|
87
|
+
raise "Table with space ID #{space_id} not found"
|
88
|
+
end
|
89
|
+
|
90
|
+
add_table(table_record["NAME"])
|
116
91
|
|
117
|
-
|
118
|
-
yield record["NAME"]
|
92
|
+
spaces[space_id]
|
119
93
|
end
|
120
94
|
|
121
|
-
|
122
|
-
|
95
|
+
# Return an Innodb::Space object by table name.
|
96
|
+
def space_by_table_name(table_name)
|
97
|
+
unless (table_record = data_dictionary.table_by_name(table_name))
|
98
|
+
raise "Table #{table_name} not found"
|
99
|
+
end
|
123
100
|
|
124
|
-
|
125
|
-
def each_orphan
|
126
|
-
unless block_given?
|
127
|
-
return enum_for(:each_orphan)
|
128
|
-
end
|
101
|
+
return if table_record["SPACE"].zero?
|
129
102
|
|
130
|
-
|
131
|
-
yield space_name
|
103
|
+
space(table_record["SPACE"])
|
132
104
|
end
|
133
105
|
|
134
|
-
|
135
|
-
|
106
|
+
# Iterate through all table names.
|
107
|
+
def each_table_name
|
108
|
+
return enum_for(:each_table_name) unless block_given?
|
136
109
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
return enum_for(:each_column_name_by_table_name, table_name)
|
141
|
-
end
|
110
|
+
data_dictionary.each_table do |record|
|
111
|
+
yield record["NAME"]
|
112
|
+
end
|
142
113
|
|
143
|
-
|
144
|
-
yield record["NAME"]
|
114
|
+
nil
|
145
115
|
end
|
146
116
|
|
147
|
-
|
148
|
-
|
117
|
+
# Iterate throught all orphaned spaces.
|
118
|
+
def each_orphan(&block)
|
119
|
+
return enum_for(:each_orphan) unless block_given?
|
149
120
|
|
150
|
-
|
151
|
-
def each_index_name_by_table_name(table_name)
|
152
|
-
unless block_given?
|
153
|
-
return enum_for(:each_index_name_by_table_name, table_name)
|
154
|
-
end
|
121
|
+
orphans.each(&block)
|
155
122
|
|
156
|
-
|
157
|
-
yield record["NAME"]
|
123
|
+
nil
|
158
124
|
end
|
159
125
|
|
160
|
-
|
161
|
-
|
126
|
+
# Iterate through all column names by table name.
|
127
|
+
def each_column_name_by_table_name(table_name)
|
128
|
+
return enum_for(:each_column_name_by_table_name, table_name) unless block_given?
|
162
129
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
table_name, index_name)
|
130
|
+
data_dictionary.each_column_by_table_name(table_name) do |record|
|
131
|
+
yield record["NAME"]
|
132
|
+
end
|
133
|
+
|
134
|
+
nil
|
169
135
|
end
|
170
136
|
|
171
|
-
|
172
|
-
|
137
|
+
# Iterate through all index names by table name.
|
138
|
+
def each_index_name_by_table_name(table_name)
|
139
|
+
return enum_for(:each_index_name_by_table_name, table_name) unless block_given?
|
140
|
+
|
141
|
+
data_dictionary.each_index_by_table_name(table_name) do |record|
|
142
|
+
yield record["NAME"]
|
143
|
+
end
|
144
|
+
|
145
|
+
nil
|
173
146
|
end
|
174
147
|
|
175
|
-
|
176
|
-
|
148
|
+
# Iterate through all field names in a given index by table name
|
149
|
+
# and index name.
|
150
|
+
def each_index_field_name_by_index_name(table_name, index_name)
|
151
|
+
return enum_for(:each_index_field_name_by_index_name, table_name, index_name) unless block_given?
|
152
|
+
|
153
|
+
data_dictionary.each_field_by_index_name(table_name, index_name) do |record|
|
154
|
+
yield record["COL_NAME"]
|
155
|
+
end
|
177
156
|
|
178
|
-
|
179
|
-
def table_name_by_id(table_id)
|
180
|
-
if table_record = data_dictionary.table_by_id(table_id)
|
181
|
-
table_record["NAME"]
|
157
|
+
nil
|
182
158
|
end
|
183
|
-
end
|
184
159
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
index_record["NAME"]
|
160
|
+
# Return the table name given a table ID.
|
161
|
+
def table_name_by_id(table_id)
|
162
|
+
data_dictionary.table_by_id(table_id).fetch("NAME", nil)
|
189
163
|
end
|
190
|
-
end
|
191
164
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
165
|
+
# Return the index name given an index ID.
|
166
|
+
def index_name_by_id(index_id)
|
167
|
+
data_dictionary.index_by_id(index_id).fetch("NAME", nil)
|
168
|
+
end
|
196
169
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
# This is a data dictionary index, which won't be found in the data
|
201
|
-
# dictionary itself.
|
202
|
-
[dd_index[:table], dd_index[:index]]
|
203
|
-
elsif index_record = data_dictionary.index_by_id(index_id)
|
204
|
-
# This is a system or user index.
|
205
|
-
[table_name_by_id(index_record["TABLE_ID"]), index_record["NAME"]]
|
170
|
+
# Return the clustered index name given a table name.
|
171
|
+
def clustered_index_by_table_name(table_name)
|
172
|
+
data_dictionary.clustered_index_name_by_table_name(table_name)
|
206
173
|
end
|
207
|
-
end
|
208
174
|
|
209
|
-
|
210
|
-
|
211
|
-
|
175
|
+
# Return an array of the table name and index name given an index ID.
|
176
|
+
def table_and_index_name_by_id(index_id)
|
177
|
+
if (dd_index = data_dictionary.data_dictionary_index_ids[index_id])
|
178
|
+
# This is a data dictionary index, which won't be found in the data
|
179
|
+
# dictionary itself.
|
180
|
+
[dd_index[:table], dd_index[:index]]
|
181
|
+
elsif (index_record = data_dictionary.index_by_id(index_id))
|
182
|
+
# This is a system or user index.
|
183
|
+
[table_name_by_id(index_record["TABLE_ID"]), index_record["NAME"]]
|
184
|
+
end
|
185
|
+
end
|
212
186
|
|
213
|
-
|
214
|
-
|
215
|
-
|
187
|
+
# Return an Innodb::Index object given a table name and index name.
|
188
|
+
def index_by_name(table_name, index_name)
|
189
|
+
index_record = data_dictionary.index_by_name(table_name, index_name)
|
216
190
|
|
217
|
-
|
218
|
-
|
191
|
+
index_space = space(index_record["SPACE"])
|
192
|
+
describer = data_dictionary.record_describer_by_index_name(table_name, index_name)
|
193
|
+
index_space.index(index_record["PAGE_NO"], describer)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Return the clustered index given a table ID.
|
197
|
+
def clustered_index_by_table_id(table_id)
|
198
|
+
table_name = table_name_by_id(table_id)
|
199
|
+
return unless table_name
|
219
200
|
|
220
|
-
# Return the clustered index given a table ID.
|
221
|
-
def clustered_index_by_table_id(table_id)
|
222
|
-
if table_name = table_name_by_id(table_id)
|
223
201
|
index_by_name(table_name, clustered_index_by_table_name(table_name))
|
224
202
|
end
|
225
|
-
end
|
226
203
|
|
227
|
-
|
228
|
-
|
204
|
+
def history
|
205
|
+
Innodb::History.new(self)
|
206
|
+
end
|
229
207
|
end
|
230
208
|
end
|