class Innodb::LogRecord
Constants
- INFO_AND_STATUS_MASK
Flag of whether an insert log record contains info and status.
- Index
- IndexFieldInfo
- LENGTH_NULL
- Preamble
- RECORD_TYPES
InnoDB log record types.
- RECORD_TYPE_MASK
- SINGLE_RECORD_MASK
Single record flag is masked in the record type.
- UNDO_TYPES
Types of undo log segments.
Attributes
Start and end LSNs for this record.
The size (in bytes) of the record.
Public Instance Methods
Dump the contents of the record.
# File lib/innodb/log_record.rb, line 102 def dump pp({ lsn: lsn, size: size, preamble: @preamble, payload: @payload }) end
# 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 the log record for delete marking or unmarking of a clustered index record. Ref. btr_cur_parse_del_mark_set_clust_rec
# 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 the index part of a log record for a compact record insert. Ref. mlog_parse_index
# 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 the insert record into page part of a insert log. Ref. page_cur_parse_insert_rec
# 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
The bodies of the branches here are sometimes duplicates, but logically distinct. rubocop:disable Lint/DuplicateBranch
# 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
Return a preamble of the first record in this block.
# 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 system fields values in a log record. Ref. row_upd_parse_sys_vals
# 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 the log record for an in-place update. Ref. btr_cur_parse_update_in_place
# 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 the update vector for an update log record. Ref. row_upd_index_parse
# 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