Class: Innodb::LogRecord
- Inherits:
-
Object
- Object
- Innodb::LogRecord
- Defined in:
- lib/innodb/log_record.rb
Defined Under Namespace
Classes: Index, IndexFieldInfo, Preamble
Constant Summary collapse
- RECORD_TYPES =
InnoDB log record types.
{ 1 => :MLOG_1BYTE, 2 => :MLOG_2BYTE, 4 => :MLOG_4BYTE, 8 => :MLOG_8BYTE, 9 => :REC_INSERT, 10 => :REC_CLUST_DELETE_MARK, 11 => :REC_SEC_DELETE_MARK, 13 => :REC_UPDATE_IN_PLACE, 14 => :REC_DELETE, 15 => :LIST_END_DELETE, 16 => :LIST_START_DELETE, 17 => :LIST_END_COPY_CREATED, 18 => :PAGE_REORGANIZE, 19 => :PAGE_CREATE, 20 => :UNDO_INSERT, 21 => :UNDO_ERASE_END, 22 => :UNDO_INIT, 23 => :UNDO_HDR_DISCARD, 24 => :UNDO_HDR_REUSE, 25 => :UNDO_HDR_CREATE, 26 => :REC_MIN_MARK, 27 => :IBUF_BITMAP_INIT, 28 => :LSN, 29 => :INIT_FILE_PAGE, 30 => :WRITE_STRING, 31 => :MULTI_REC_END, 32 => :DUMMY_RECORD, 33 => :FILE_CREATE, 34 => :FILE_RENAME, 35 => :FILE_DELETE, 36 => :COMP_REC_MIN_MARK, 37 => :COMP_PAGE_CREATE, 38 => :COMP_REC_INSERT, 39 => :COMP_REC_CLUST_DELETE_MARK, 40 => :COMP_REC_SEC_DELETE_MARK, 41 => :COMP_REC_UPDATE_IN_PLACE, 42 => :COMP_REC_DELETE, 43 => :COMP_LIST_END_DELETE, 44 => :COMP_LIST_START_DELETE, 45 => :COMP_LIST_END_COPY_CREATE, 46 => :COMP_PAGE_REORGANIZE, 47 => :FILE_CREATE2, 48 => :ZIP_WRITE_NODE_PTR, 49 => :ZIP_WRITE_BLOB_PTR, 50 => :ZIP_WRITE_HEADER, 51 => :ZIP_PAGE_COMPRESS, }.freeze
- UNDO_TYPES =
Types of undo log segments.
{ 1 => :UNDO_INSERT, 2 => :UNDO_UPDATE, }.freeze
- SINGLE_RECORD_MASK =
Single record flag is masked in the record type.
0x80
- RECORD_TYPE_MASK =
0x7f
- INFO_AND_STATUS_MASK =
Flag of whether an insert log record contains info and status.
0x1
- LENGTH_NULL =
0xFFFFFFFF
Instance Attribute Summary collapse
-
#lsn ⇒ Object
Start and end LSNs for this record.
-
#payload ⇒ Object
readonly
Returns the value of attribute payload.
-
#preamble ⇒ Object
readonly
Returns the value of attribute preamble.
-
#size ⇒ Object
readonly
The size (in bytes) of the record.
Instance Method Summary collapse
-
#dump ⇒ Object
Dump the contents of the record.
- #read(cursor) ⇒ Object
-
#read_clust_delete_mark(cursor) ⇒ Object
Read the log record for delete marking or unmarking of a clustered index record.
-
#read_index(cursor) ⇒ Object
Read the index part of a log record for a compact record insert.
-
#read_insert_record(cursor) ⇒ Object
Read the insert record into page part of a insert log.
-
#read_payload(type, cursor) ⇒ Object
The bodies of the branches here are sometimes duplicates, but logically distinct.
-
#read_preamble(cursor) ⇒ Object
Return a preamble of the first record in this block.
-
#read_sys_fields(cursor) ⇒ Object
Read system fields values in a log record.
-
#read_update_in_place_record(cursor) ⇒ Object
Read the log record for an in-place update.
-
#read_update_index(cursor) ⇒ Object
Read the update vector for an update log record.
Instance Attribute Details
#lsn ⇒ Object
Start and end LSNs for this record.
29 30 31 |
# File 'lib/innodb/log_record.rb', line 29 def lsn @lsn end |
#payload ⇒ Object (readonly)
Returns the value of attribute payload.
36 37 38 |
# File 'lib/innodb/log_record.rb', line 36 def payload @payload end |
#preamble ⇒ Object (readonly)
Returns the value of attribute preamble.
34 35 36 |
# File 'lib/innodb/log_record.rb', line 34 def preamble @preamble end |
#size ⇒ Object (readonly)
The size (in bytes) of the record.
32 33 34 |
# File 'lib/innodb/log_record.rb', line 32 def size @size end |
Instance Method Details
#dump ⇒ Object
Dump the contents of the record.
102 103 104 |
# File 'lib/innodb/log_record.rb', line 102 def dump pp({ lsn: lsn, size: size, preamble: @preamble, payload: @payload }) end |
#read(cursor) ⇒ Object
94 95 96 97 98 99 |
# File 'lib/innodb/log_record.rb', line 94 def read(cursor) origin = cursor.position @preamble = read_preamble(cursor) @payload = read_payload(@preamble.type, cursor) @size = cursor.position - origin end |
#read_clust_delete_mark(cursor) ⇒ Object
Read the log record for delete marking or unmarking of a clustered index record. Ref. btr_cur_parse_del_mark_set_clust_rec
217 218 219 220 221 222 223 224 |
# File 'lib/innodb/log_record.rb', line 217 def read_clust_delete_mark(cursor) { flags: cursor.name("flags") { cursor.read_uint8 }, value: cursor.name("value") { cursor.read_uint8 }, sys_fields: cursor.name("sys_fields") { read_sys_fields(cursor) }, offset: cursor.name("offset") { cursor.read_uint16 }, } end |
#read_index(cursor) ⇒ Object
Read the index part of a log record for a compact record insert. Ref. mlog_parse_index
132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/innodb/log_record.rb', line 132 def read_index(cursor) n_cols = cursor.name("n_cols") { cursor.read_uint16 } n_uniq = cursor.name("n_uniq") { cursor.read_uint16 } cols = n_cols.times.collect do info = cursor.name("field_info") { cursor.read_uint16 } IndexFieldInfo.new( mtype: ((info + 1) & 0x7fff) <= 1 ? :BINARY : :FIXBINARY, prtype: (info & 0x8000).zero? ? nil : :NOT_NULL, length: info & 0x7fff ) end Index.new(n_cols: n_cols, n_uniq: n_uniq, cols: cols) end |
#read_insert_record(cursor) ⇒ Object
Read the insert record into page part of a insert log. Ref. page_cur_parse_insert_rec
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/innodb/log_record.rb', line 152 def read_insert_record(cursor) page_offset = cursor.name("page_offset") { cursor.read_uint16 } end_seg_len = cursor.name("end_seg_len") { cursor.read_ic_uint32 } if (end_seg_len & INFO_AND_STATUS_MASK) != 0 info_and_status_bits = cursor.read_uint8 origin_offset = cursor.read_ic_uint32 mismatch_index = cursor.read_ic_uint32 end { page_offset: page_offset, end_seg_len: end_seg_len >> 1, info_and_status_bits: info_and_status_bits, origin_offset: origin_offset, mismatch_index: mismatch_index, record: cursor.name("record") { cursor.read_bytes(end_seg_len >> 1) }, } end |
#read_payload(type, cursor) ⇒ Object
The bodies of the branches here are sometimes duplicates, but logically distinct. rubocop:disable Lint/DuplicateBranch
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/innodb/log_record.rb', line 228 def read_payload(type, cursor) case type when :MLOG_1BYTE, :MLOG_2BYTE, :MLOG_4BYTE { page_offset: cursor.name("page_offset") { cursor.read_uint16 }, value: cursor.name("value") { cursor.read_ic_uint32 }, } when :MLOG_8BYTE { offset: cursor.name("offset") { cursor.read_uint16 }, value: cursor.name("value") { cursor.read_ic_uint64 }, } when :UNDO_HDR_CREATE, :UNDO_HDR_REUSE { trx_id: cursor.name("trx_id") { cursor.read_ic_uint64 }, } when :UNDO_INSERT { length: length = cursor.name("length") { cursor.read_uint16 }, value: cursor.name("value") { cursor.read_bytes(length) }, } when :REC_INSERT { record: cursor.name("record") { read_insert_record(cursor) }, } when :COMP_REC_INSERT { index: cursor.name("index") { read_index(cursor) }, record: cursor.name("record") { read_insert_record(cursor) }, } when :COMP_REC_UPDATE_IN_PLACE { index: cursor.name("index") { read_index(cursor) }, record: cursor.name("record") { read_update_in_place_record(cursor) }, } when :REC_UPDATE_IN_PLACE { record: cursor.name("record") { read_update_in_place_record(cursor) }, } when :WRITE_STRING { offset: cursor.name("offset") { cursor.read_uint16 }, length: length = cursor.name("length") { cursor.read_uint16 }, value: cursor.name("value") { cursor.read_bytes(length) }, } when :UNDO_INIT { type: cursor.name("type") { UNDO_TYPES[cursor.read_ic_uint32] }, } when :FILE_CREATE, :FILE_DELETE { name_len: name_len = cursor.name("name_len") { cursor.read_uint16 }, name: cursor.name("name") { cursor.read_bytes(name_len) }, } when :FILE_CREATE2 { flags: cursor.name("flags") { cursor.read_uint32 }, name_len: name_len = cursor.name("name_len") { cursor.read_uint16 }, name: cursor.name("name") { cursor.read_bytes(name_len) }, } when :FILE_RENAME { old: { name_len: name_len = cursor.name("name_len") { cursor.read_uint16 }, name: cursor.name("name") { cursor.read_bytes(name_len) }, }, new: { name_len: name_len = cursor.name("name_len") { cursor.read_uint16 }, name: cursor.name("name") { cursor.read_bytes(name_len) }, }, } when :COMP_REC_CLUST_DELETE_MARK { index: cursor.name("index") { read_index(cursor) }, record: cursor.name("record") { read_clust_delete_mark(cursor) }, } when :REC_CLUST_DELETE_MARK { record: cursor.name("record") { read_clust_delete_mark(cursor) }, } when :COMP_REC_SEC_DELETE_MARK { index: cursor.name("index") { read_index(cursor) }, value: cursor.name("value") { cursor.read_uint8 }, offset: cursor.name("offset") { cursor.read_uint16 }, } when :REC_SEC_DELETE_MARK { value: cursor.name("value") { cursor.read_uint8 }, offset: cursor.name("offset") { cursor.read_uint16 }, } when :REC_DELETE { offset: cursor.name("offset") { cursor.read_uint16 }, } when :COMP_REC_DELETE { index: cursor.name("index") { read_index(cursor) }, offset: cursor.name("offset") { cursor.read_uint16 }, } when :REC_MIN_MARK, :COMP_REC_MIN_MARK { offset: cursor.name("offset") { cursor.read_uint16 }, } when :LIST_START_DELETE, :LIST_END_DELETE { offset: cursor.name("offset") { cursor.read_uint16 }, } when :COMP_LIST_START_DELETE, :COMP_LIST_END_DELETE { index: cursor.name("index") { read_index(cursor) }, offset: cursor.name("offset") { cursor.read_uint16 }, } when :LIST_END_COPY_CREATED { length: length = cursor.name("length") { cursor.read_uint32 }, data: cursor.name("data") { cursor.read_bytes(length) }, } when :COMP_LIST_END_COPY_CREATE { index: cursor.name("index") { read_index(cursor) }, length: length = cursor.name("length") { cursor.read_uint32 }, data: cursor.name("data") { cursor.read_bytes(length) }, } when :COMP_PAGE_REORGANIZE { index: cursor.name("index") { read_index(cursor) }, } when :DUMMY_RECORD, :MULTI_REC_END, :INIT_FILE_PAGE, :IBUF_BITMAP_INIT, :PAGE_CREATE, :COMP_PAGE_CREATE, :PAGE_REORGANIZE, :UNDO_ERASE_END, :UNDO_HDR_DISCARD {} else raise "Unsupported log record type: #{type}" end end |
#read_preamble(cursor) ⇒ Object
Return a preamble of the first record in this block.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/innodb/log_record.rb', line 111 def read_preamble(cursor) type_and_flag = cursor.name("type") { cursor.read_uint8 } type = type_and_flag & RECORD_TYPE_MASK type = RECORD_TYPES[type] || type # Whether this is a single record for a single page. single_record = (type_and_flag & SINGLE_RECORD_MASK).positive? case type when :MULTI_REC_END, :DUMMY_RECORD Preamble.new(type: type) else Preamble.new( type: type, single_record: single_record, space: cursor.name("space") { cursor.read_ic_uint32 }, page_number: cursor.name("page_number") { cursor.read_ic_uint32 } ) end end |
#read_sys_fields(cursor) ⇒ Object
Read system fields values in a log record. Ref. row_upd_parse_sys_vals
206 207 208 209 210 211 212 |
# File 'lib/innodb/log_record.rb', line 206 def read_sys_fields(cursor) { trx_id_pos: cursor.name("trx_id_pos") { cursor.read_ic_uint32 }, roll_ptr: cursor.name("roll_ptr") { cursor.read_bytes(7) }, trx_id: cursor.name("trx_id") { cursor.read_ic_uint64 }, } end |
#read_update_in_place_record(cursor) ⇒ Object
Read the log record for an in-place update. Ref. btr_cur_parse_update_in_place
174 175 176 177 178 179 180 181 |
# File 'lib/innodb/log_record.rb', line 174 def read_update_in_place_record(cursor) { flags: cursor.name("flags") { cursor.read_uint8 }, sys_fields: read_sys_fields(cursor), rec_offset: cursor.name("rec_offset") { cursor.read_uint16 }, update_index: read_update_index(cursor), } end |
#read_update_index(cursor) ⇒ Object
Read the update vector for an update log record. Ref. row_upd_index_parse
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/innodb/log_record.rb', line 187 def read_update_index(cursor) info_bits = cursor.name("info_bits") { cursor.read_uint8 } n_fields = cursor.name("n_fields") { cursor.read_ic_uint32 } fields = n_fields.times.collect do { field_no: cursor.name("field_no") { cursor.read_ic_uint32 }, len: len = cursor.name("len") { cursor.read_ic_uint32 }, data: cursor.name("data") { len == LENGTH_NULL ? :NULL : cursor.read_bytes(len) }, } end { info_bits: info_bits, n_fields: n_fields, fields: fields, } end |