innodb_ruby 0.9.13 → 0.11.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 +14 -19
- data/bin/innodb_space +592 -745
- data/lib/innodb.rb +5 -5
- 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 -275
- data/lib/innodb/inode.rb +166 -124
- data/lib/innodb/list.rb +191 -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.rb +446 -291
- 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/record.rb +121 -164
- data/lib/innodb/record_describer.rb +66 -68
- data/lib/innodb/space.rb +386 -391
- 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
- metadata +112 -21
data/lib/innodb/page/undo_log.rb
CHANGED
@@ -1,95 +1,109 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Innodb
|
4
|
+
class Page
|
5
|
+
class UndoLog < Page
|
6
|
+
specialization_for :UNDO_LOG
|
7
|
+
|
8
|
+
PageHeader = Struct.new(
|
9
|
+
:type,
|
10
|
+
:latest_log_record_offset,
|
11
|
+
:free_offset,
|
12
|
+
:page_list_node,
|
13
|
+
keyword_init: true
|
14
|
+
)
|
15
|
+
|
16
|
+
SegmentHeader = Struct.new(
|
17
|
+
:state,
|
18
|
+
:last_log_offset,
|
19
|
+
:fseg,
|
20
|
+
:page_list,
|
21
|
+
keyword_init: true
|
22
|
+
)
|
23
|
+
|
24
|
+
def pos_undo_page_header
|
25
|
+
pos_page_body
|
26
|
+
end
|
27
|
+
|
28
|
+
def size_undo_page_header
|
29
|
+
2 + 2 + 2 + Innodb::List::NODE_SIZE
|
30
|
+
end
|
31
|
+
|
32
|
+
def pos_undo_segment_header
|
33
|
+
pos_undo_page_header + size_undo_page_header
|
34
|
+
end
|
35
|
+
|
36
|
+
def size_undo_segment_header
|
37
|
+
2 + 2 + Innodb::FsegEntry::SIZE + Innodb::List::BASE_NODE_SIZE
|
38
|
+
end
|
39
|
+
|
40
|
+
def pos_undo_logs
|
41
|
+
pos_undo_segment_header + size_undo_segment_header
|
42
|
+
end
|
43
|
+
|
44
|
+
UNDO_PAGE_TYPES = {
|
45
|
+
1 => :insert,
|
46
|
+
2 => :update,
|
47
|
+
}.freeze
|
48
|
+
|
49
|
+
UNDO_SEGMENT_STATES = {
|
50
|
+
1 => :active,
|
51
|
+
2 => :cached,
|
52
|
+
3 => :to_free,
|
53
|
+
4 => :to_purge,
|
54
|
+
5 => :prepared,
|
55
|
+
}.freeze
|
56
|
+
|
57
|
+
def undo_page_header
|
58
|
+
@undo_page_header ||= cursor(pos_undo_page_header).name("undo_page_header") do |c|
|
59
|
+
PageHeader.new(
|
60
|
+
type: c.name("type") { UNDO_PAGE_TYPES[c.read_uint16] },
|
61
|
+
latest_log_record_offset: c.name("latest_log_record_offset") { c.read_uint16 },
|
62
|
+
free_offset: c.name("free_offset") { c.read_uint16 },
|
63
|
+
page_list_node: c.name("page_list") { Innodb::List.get_node(c) }
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def prev_address
|
69
|
+
undo_page_header[:page_list_node][:prev]
|
70
|
+
end
|
71
|
+
|
72
|
+
def next_address
|
73
|
+
undo_page_header[:page_list_node][:next]
|
74
|
+
end
|
75
|
+
|
76
|
+
def undo_segment_header
|
77
|
+
@undo_segment_header ||= cursor(pos_undo_segment_header).name("undo_segment_header") do |c|
|
78
|
+
SegmentHeader.new(
|
79
|
+
state: c.name("state") { UNDO_SEGMENT_STATES[c.read_uint16] },
|
80
|
+
last_log_offset: c.name("last_log_offset") { c.read_uint16 },
|
81
|
+
fseg: c.name("fseg") { Innodb::FsegEntry.get_inode(@space, c) },
|
82
|
+
page_list: c.name("page_list") { Innodb::List::UndoPage.new(@space, Innodb::List.get_base_node(c)) }
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def undo_log(pos)
|
88
|
+
Innodb::UndoLog.new(self, pos)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Dump the contents of a page for debugging purposes.
|
92
|
+
def dump
|
93
|
+
super
|
94
|
+
|
95
|
+
puts "undo page header:"
|
96
|
+
pp undo_page_header
|
97
|
+
puts
|
98
|
+
|
99
|
+
puts "undo segment header:"
|
100
|
+
pp undo_segment_header
|
101
|
+
puts
|
102
|
+
|
103
|
+
puts "last undo log:"
|
104
|
+
undo_log(undo_segment_header[:last_log_offset]).dump unless undo_segment_header[:last_log_offset].zero?
|
105
|
+
puts
|
106
|
+
end
|
46
107
|
end
|
47
108
|
end
|
48
|
-
|
49
|
-
def prev_address
|
50
|
-
undo_page_header[:page_list_node][:prev]
|
51
|
-
end
|
52
|
-
|
53
|
-
def next_address
|
54
|
-
undo_page_header[:page_list_node][:next]
|
55
|
-
end
|
56
|
-
|
57
|
-
def undo_segment_header
|
58
|
-
@undo_segment_header ||=
|
59
|
-
cursor(pos_undo_segment_header).name("undo_segment_header") do |c|
|
60
|
-
{
|
61
|
-
:state => c.name("state") { UNDO_SEGMENT_STATES[c.get_uint16] },
|
62
|
-
:last_log_offset => c.name("last_log_offset") { c.get_uint16 },
|
63
|
-
:fseg => c.name("fseg") { Innodb::FsegEntry.get_inode(@space, c) },
|
64
|
-
:page_list => c.name("page_list") {
|
65
|
-
Innodb::List::UndoPage.new(@space, Innodb::List.get_base_node(c))
|
66
|
-
},
|
67
|
-
}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def undo_log(pos)
|
72
|
-
Innodb::UndoLog.new(self, pos)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Dump the contents of a page for debugging purposes.
|
76
|
-
def dump
|
77
|
-
super
|
78
|
-
|
79
|
-
puts "undo page header:"
|
80
|
-
pp undo_page_header
|
81
|
-
puts
|
82
|
-
|
83
|
-
puts "undo segment header:"
|
84
|
-
pp undo_segment_header
|
85
|
-
puts
|
86
|
-
|
87
|
-
puts "last undo log:"
|
88
|
-
if undo_segment_header[:last_log_offset] != 0
|
89
|
-
undo_log(undo_segment_header[:last_log_offset]).dump
|
90
|
-
end
|
91
|
-
puts
|
92
|
-
end
|
93
109
|
end
|
94
|
-
|
95
|
-
Innodb::Page::SPECIALIZED_CLASSES[:UNDO_LOG] = Innodb::Page::UndoLog
|
data/lib/innodb/record.rb
CHANGED
@@ -1,199 +1,156 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
attr_reader :page
|
5
|
-
attr_accessor :record
|
3
|
+
require "forwardable"
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
def header
|
13
|
-
record[:header]
|
14
|
-
end
|
15
|
-
|
16
|
-
def next
|
17
|
-
header[:next]
|
18
|
-
end
|
19
|
-
|
20
|
-
def type
|
21
|
-
header[:type]
|
22
|
-
end
|
5
|
+
module Innodb
|
6
|
+
class Record
|
7
|
+
extend Forwardable
|
23
8
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def n_owned
|
29
|
-
header[:n_owned]
|
30
|
-
end
|
31
|
-
|
32
|
-
def deleted?
|
33
|
-
header[:deleted]
|
34
|
-
end
|
35
|
-
|
36
|
-
def min_rec?
|
37
|
-
header[:min_rec]
|
38
|
-
end
|
9
|
+
attr_reader :page
|
10
|
+
attr_accessor :record
|
39
11
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
def length
|
45
|
-
record[:length]
|
46
|
-
end
|
47
|
-
|
48
|
-
def next
|
49
|
-
record[:next]
|
50
|
-
end
|
51
|
-
|
52
|
-
def key
|
53
|
-
record[:key]
|
54
|
-
end
|
12
|
+
def initialize(page, record)
|
13
|
+
@page = page
|
14
|
+
@record = record
|
15
|
+
end
|
55
16
|
|
56
|
-
|
57
|
-
|
58
|
-
|
17
|
+
def_delegator :record, :header
|
18
|
+
def_delegator :record, :offset
|
19
|
+
def_delegator :record, :length
|
20
|
+
def_delegator :record, :next
|
21
|
+
def_delegator :record, :key
|
22
|
+
def_delegator :record, :row
|
23
|
+
def_delegator :record, :transaction_id
|
24
|
+
def_delegator :record, :roll_pointer
|
25
|
+
def_delegator :record, :child_page_number
|
26
|
+
|
27
|
+
def_delegator :header, :type
|
28
|
+
def_delegator :header, :heap_number
|
29
|
+
def_delegator :header, :n_owned
|
30
|
+
def_delegator :header, :heap_number
|
31
|
+
def_delegator :header, :deleted?
|
32
|
+
def_delegator :header, :min_rec?
|
33
|
+
|
34
|
+
def key_string
|
35
|
+
key&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
|
36
|
+
end
|
59
37
|
|
60
|
-
|
61
|
-
|
62
|
-
|
38
|
+
def row_string
|
39
|
+
row&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
|
40
|
+
end
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
42
|
+
def undo
|
43
|
+
return nil unless roll_pointer
|
44
|
+
return unless (innodb_system = @page.space.innodb_system)
|
67
45
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
46
|
+
undo_page = innodb_system.system_space.page(roll_pointer.undo_log.page)
|
47
|
+
return unless undo_page
|
71
48
|
|
72
|
-
|
73
|
-
|
74
|
-
|
49
|
+
new_undo_record = Innodb::UndoRecord.new(undo_page, roll_pointer.undo_log.offset)
|
50
|
+
new_undo_record.index_page = page
|
51
|
+
new_undo_record
|
52
|
+
end
|
75
53
|
|
76
|
-
|
77
|
-
|
54
|
+
def each_undo_record
|
55
|
+
return enum_for(:each_undo_record) unless block_given?
|
78
56
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
new_undo_record.index_page = page
|
84
|
-
new_undo_record
|
57
|
+
undo_record = undo
|
58
|
+
while undo_record
|
59
|
+
yield undo_record
|
60
|
+
undo_record = undo_record.prev_by_history
|
85
61
|
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def each_undo_record
|
90
|
-
unless block_given?
|
91
|
-
return enum_for(:each_undo_record)
|
92
|
-
end
|
93
62
|
|
94
|
-
|
95
|
-
while undo_record
|
96
|
-
yield undo_record
|
97
|
-
undo_record = undo_record.prev_by_history
|
63
|
+
nil
|
98
64
|
end
|
99
65
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
def string
|
108
|
-
if child_page_number
|
109
|
-
"(%s) → #%s" % [key_string, child_page_number]
|
110
|
-
else
|
111
|
-
"(%s) → (%s)" % [key_string, row_string]
|
66
|
+
def string
|
67
|
+
if child_page_number
|
68
|
+
"(%s) → #%s" % [key_string, child_page_number]
|
69
|
+
else
|
70
|
+
"(%s) → (%s)" % [key_string, row_string]
|
71
|
+
end
|
112
72
|
end
|
113
|
-
end
|
114
73
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
fields_hash[column[:name]] = column[:value]
|
74
|
+
def uncached_fields
|
75
|
+
fields_hash = {}
|
76
|
+
%i[key row].each do |group|
|
77
|
+
record[group]&.each do |column|
|
78
|
+
fields_hash[column.name] = column.value
|
121
79
|
end
|
122
80
|
end
|
81
|
+
fields_hash
|
123
82
|
end
|
124
|
-
fields_hash
|
125
|
-
end
|
126
83
|
|
127
|
-
|
128
|
-
|
129
|
-
|
84
|
+
def fields
|
85
|
+
@fields ||= uncached_fields
|
86
|
+
end
|
87
|
+
|
88
|
+
# Compare two arrays of fields to determine if they are equal. This follows
|
89
|
+
# the same comparison rules as strcmp and others:
|
90
|
+
# 0 = a is equal to b
|
91
|
+
# -1 = a is less than b
|
92
|
+
# +1 = a is greater than b
|
93
|
+
def compare_key(other_key)
|
94
|
+
Innodb::Stats.increment :compare_key
|
95
|
+
|
96
|
+
return 0 if other_key.nil? && key.nil?
|
97
|
+
return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
|
98
|
+
return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
|
99
|
+
|
100
|
+
key.each_index do |i|
|
101
|
+
Innodb::Stats.increment :compare_key_field_comparison
|
102
|
+
return -1 if other_key[i] < key[i].value
|
103
|
+
return +1 if other_key[i] > key[i].value
|
104
|
+
end
|
130
105
|
|
131
|
-
|
132
|
-
# the same comparison rules as strcmp and others:
|
133
|
-
# 0 = a is equal to b
|
134
|
-
# -1 = a is less than b
|
135
|
-
# +1 = a is greater than b
|
136
|
-
def compare_key(other_key)
|
137
|
-
Innodb::Stats.increment :compare_key
|
138
|
-
|
139
|
-
return 0 if other_key.nil? && key.nil?
|
140
|
-
return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
|
141
|
-
return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
|
142
|
-
|
143
|
-
key.each_index do |i|
|
144
|
-
Innodb::Stats.increment :compare_key_field_comparison
|
145
|
-
return -1 if other_key[i] < key[i][:value]
|
146
|
-
return +1 if other_key[i] > key[i][:value]
|
106
|
+
0
|
147
107
|
end
|
148
108
|
|
149
|
-
|
150
|
-
|
109
|
+
def dump
|
110
|
+
puts "Record at offset %i" % offset
|
111
|
+
puts
|
151
112
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
puts " %-20s: %i" % ["Heap number", header[:heap_number]]
|
159
|
-
puts " %-20s: %s" % ["Type", header[:type]]
|
160
|
-
puts " %-20s: %s" % ["Deleted", header[:deleted]]
|
161
|
-
puts " %-20s: %s" % ["Length", header[:length]]
|
162
|
-
puts
|
163
|
-
|
164
|
-
if page.leaf?
|
165
|
-
puts "System fields:"
|
166
|
-
puts " Transaction ID: %s" % transaction_id
|
167
|
-
puts " Roll Pointer:"
|
168
|
-
puts " Undo Log: page %i, offset %i" % [
|
169
|
-
roll_pointer[:undo_log][:page],
|
170
|
-
roll_pointer[:undo_log][:offset],
|
171
|
-
]
|
172
|
-
puts " Rollback Segment ID: %i" % roll_pointer[:rseg_id]
|
173
|
-
puts " Insert: %s" % roll_pointer[:is_insert]
|
113
|
+
puts "Header:"
|
114
|
+
puts " %-20s: %i" % ["Next record offset", header.next]
|
115
|
+
puts " %-20s: %i" % ["Heap number", header.heap_number]
|
116
|
+
puts " %-20s: %s" % ["Type", header.type]
|
117
|
+
puts " %-20s: %s" % ["Deleted", header.deleted?]
|
118
|
+
puts " %-20s: %s" % ["Length", header.length]
|
174
119
|
puts
|
175
|
-
end
|
176
120
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
121
|
+
if page.leaf?
|
122
|
+
puts "System fields:"
|
123
|
+
puts " Transaction ID: %s" % transaction_id
|
124
|
+
puts " Roll Pointer:"
|
125
|
+
puts " Undo Log: page %i, offset %i" % [
|
126
|
+
roll_pointer.undo_log.page,
|
127
|
+
roll_pointer.undo_log.offset,
|
128
|
+
]
|
129
|
+
puts " Rollback Segment ID: %i" % roll_pointer.rseg_id
|
130
|
+
puts " Insert: %s" % roll_pointer.is_insert
|
131
|
+
puts
|
132
|
+
end
|
185
133
|
|
186
|
-
|
187
|
-
|
188
|
-
row.each do |field|
|
134
|
+
puts "Key fields:"
|
135
|
+
key.each do |field|
|
189
136
|
puts " %s: %s" % [
|
190
|
-
field
|
191
|
-
field
|
137
|
+
field.name,
|
138
|
+
field.value.inspect,
|
192
139
|
]
|
193
140
|
end
|
194
141
|
puts
|
195
|
-
|
196
|
-
|
142
|
+
|
143
|
+
if page.leaf?
|
144
|
+
puts "Non-key fields:"
|
145
|
+
row.each do |field|
|
146
|
+
puts " %s: %s" % [
|
147
|
+
field.name,
|
148
|
+
field.value.inspect,
|
149
|
+
]
|
150
|
+
end
|
151
|
+
else
|
152
|
+
puts "Child page number: %i" % child_page_number
|
153
|
+
end
|
197
154
|
puts
|
198
155
|
end
|
199
156
|
end
|