innodb_ruby 0.9.16 → 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 +5 -5
- data/README.md +5 -6
- data/bin/innodb_log +13 -18
- data/bin/innodb_space +377 -757
- data/lib/innodb.rb +4 -5
- data/lib/innodb/checksum.rb +26 -24
- data/lib/innodb/data_dictionary.rb +490 -550
- data/lib/innodb/data_type.rb +362 -326
- 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 +154 -155
- 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 +417 -414
- 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 +964 -943
- 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 -160
- data/lib/innodb/record_describer.rb +66 -68
- data/lib/innodb/space.rb +380 -418
- 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 +80 -11
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,195 +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 type
|
17
|
-
header[:type]
|
18
|
-
end
|
19
|
-
|
20
|
-
def heap_number
|
21
|
-
header[:heap_number]
|
22
|
-
end
|
23
|
-
|
24
|
-
def n_owned
|
25
|
-
header[:n_owned]
|
26
|
-
end
|
27
|
-
|
28
|
-
def deleted?
|
29
|
-
header[:deleted]
|
30
|
-
end
|
31
|
-
|
32
|
-
def min_rec?
|
33
|
-
header[:min_rec]
|
34
|
-
end
|
5
|
+
module Innodb
|
6
|
+
class Record
|
7
|
+
extend Forwardable
|
35
8
|
|
36
|
-
|
37
|
-
record
|
38
|
-
end
|
39
|
-
|
40
|
-
def length
|
41
|
-
record[:length]
|
42
|
-
end
|
9
|
+
attr_reader :page
|
10
|
+
attr_accessor :record
|
43
11
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def key
|
49
|
-
record[:key]
|
50
|
-
end
|
12
|
+
def initialize(page, record)
|
13
|
+
@page = page
|
14
|
+
@record = record
|
15
|
+
end
|
51
16
|
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
55
37
|
|
56
|
-
|
57
|
-
|
58
|
-
|
38
|
+
def row_string
|
39
|
+
row&.map { |r| "%s=%s" % [r.name, r.value.inspect] }&.join(", ")
|
40
|
+
end
|
59
41
|
|
60
|
-
|
61
|
-
|
62
|
-
|
42
|
+
def undo
|
43
|
+
return nil unless roll_pointer
|
44
|
+
return unless (innodb_system = @page.space.innodb_system)
|
63
45
|
|
64
|
-
|
65
|
-
|
66
|
-
end
|
46
|
+
undo_page = innodb_system.system_space.page(roll_pointer.undo_log.page)
|
47
|
+
return unless undo_page
|
67
48
|
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
71
53
|
|
72
|
-
|
73
|
-
|
54
|
+
def each_undo_record
|
55
|
+
return enum_for(:each_undo_record) unless block_given?
|
74
56
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
new_undo_record.index_page = page
|
80
|
-
new_undo_record
|
57
|
+
undo_record = undo
|
58
|
+
while undo_record
|
59
|
+
yield undo_record
|
60
|
+
undo_record = undo_record.prev_by_history
|
81
61
|
end
|
82
|
-
end
|
83
|
-
end
|
84
62
|
|
85
|
-
|
86
|
-
unless block_given?
|
87
|
-
return enum_for(:each_undo_record)
|
63
|
+
nil
|
88
64
|
end
|
89
65
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
nil
|
97
|
-
end
|
98
|
-
|
99
|
-
def child_page_number
|
100
|
-
record[:child_page_number]
|
101
|
-
end
|
102
|
-
|
103
|
-
def string
|
104
|
-
if child_page_number
|
105
|
-
"(%s) → #%s" % [key_string, child_page_number]
|
106
|
-
else
|
107
|
-
"(%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
|
108
72
|
end
|
109
|
-
end
|
110
73
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
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
|
117
79
|
end
|
118
80
|
end
|
81
|
+
fields_hash
|
119
82
|
end
|
120
|
-
fields_hash
|
121
|
-
end
|
122
83
|
|
123
|
-
|
124
|
-
|
125
|
-
|
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
|
126
105
|
|
127
|
-
|
128
|
-
# the same comparison rules as strcmp and others:
|
129
|
-
# 0 = a is equal to b
|
130
|
-
# -1 = a is less than b
|
131
|
-
# +1 = a is greater than b
|
132
|
-
def compare_key(other_key)
|
133
|
-
Innodb::Stats.increment :compare_key
|
134
|
-
|
135
|
-
return 0 if other_key.nil? && key.nil?
|
136
|
-
return -1 if other_key.nil? || (!key.nil? && other_key.size < key.size)
|
137
|
-
return +1 if key.nil? || (!other_key.nil? && other_key.size > key.size)
|
138
|
-
|
139
|
-
key.each_index do |i|
|
140
|
-
Innodb::Stats.increment :compare_key_field_comparison
|
141
|
-
return -1 if other_key[i] < key[i][:value]
|
142
|
-
return +1 if other_key[i] > key[i][:value]
|
106
|
+
0
|
143
107
|
end
|
144
108
|
|
145
|
-
|
146
|
-
|
109
|
+
def dump
|
110
|
+
puts "Record at offset %i" % offset
|
111
|
+
puts
|
147
112
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
puts " %-20s: %i" % ["Heap number", header[:heap_number]]
|
155
|
-
puts " %-20s: %s" % ["Type", header[:type]]
|
156
|
-
puts " %-20s: %s" % ["Deleted", header[:deleted]]
|
157
|
-
puts " %-20s: %s" % ["Length", header[:length]]
|
158
|
-
puts
|
159
|
-
|
160
|
-
if page.leaf?
|
161
|
-
puts "System fields:"
|
162
|
-
puts " Transaction ID: %s" % transaction_id
|
163
|
-
puts " Roll Pointer:"
|
164
|
-
puts " Undo Log: page %i, offset %i" % [
|
165
|
-
roll_pointer[:undo_log][:page],
|
166
|
-
roll_pointer[:undo_log][:offset],
|
167
|
-
]
|
168
|
-
puts " Rollback Segment ID: %i" % roll_pointer[:rseg_id]
|
169
|
-
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]
|
170
119
|
puts
|
171
|
-
end
|
172
120
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|
181
133
|
|
182
|
-
|
183
|
-
|
184
|
-
row.each do |field|
|
134
|
+
puts "Key fields:"
|
135
|
+
key.each do |field|
|
185
136
|
puts " %s: %s" % [
|
186
|
-
field
|
187
|
-
field
|
137
|
+
field.name,
|
138
|
+
field.value.inspect,
|
188
139
|
]
|
189
140
|
end
|
190
141
|
puts
|
191
|
-
|
192
|
-
|
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
|
193
154
|
puts
|
194
155
|
end
|
195
156
|
end
|