1. 每个事务开始时,都会分配一个ROLLBACK SEG给这个事务(即trx_sys_struct->rseg_array[]数组中的一个元素, 这个数组中的元素由链表[trx_sys->rseg_list]来管理,在链表中选择segment是采用ROUND-ROBIN的方式来。即trx_sys_struct->latest_rseg来指示最新被使用的rollback segment)
2. 当需要写一个undo log时,会申请一个trx_undo_t最为一个undo log的管理结构,一个trx_undo_t用于对应T
RX_RSEG_UNDO_SLOTS,即一个
UNDO LOG SEGMENT PAGE。一个事务可能会写多个undo log,每次要写时都需要申请一个trx_undo_t,并且对应一个TRX_RSEG_UNDO_SLOTS。并且在对应的
UNDO LOG SEGMENT PAGE创建一个undo log header。多个undo log header在trx_undo_t重用是会存在(见4)。
3. 当一个页的空闲空间不够时,会申请一个
Undo log normal page
, 这个页没有TRX_UNDO_SEG_HDR,即没有UNDO LOG SEGMENT头。
4. InnoDB为了分配undo slot的性能考虑,做了一个小小的优化
事务提交时,事务对应的undo slot并不一定立即释放,而是cache起来 可以被cache起来的undo slot的条件如下:
(1).当前undo只占用一个undo page (cache起来代价较小,不至于消耗空间)
(2). 当前undo对应的undo page,仍旧有足够的空闲空间,可以存放下一个
undo的第一条undo头记录。
5. 事务COMMIT时,对应UPDATE操作,将对应的UNDO LOG HEADER
添加到本UNDO LOG对应的
TRX_RSEG_HISTORY
的头部,然后会有PURGE THREAD会根据UNDO LOG对数据库进行操作(即DELETE只是在记录中标识了删除的标志[MVCC的需要],没有进行真正的删除,真正的删除有PURGE线程进行删除). 而对于INSERT操作,由于已经在数据库中进行了插入操作,因此只需将相应的UNDO LOG释放。
TRX SYSTEM PAGE
|
|
TRX_SYS_TRX_ID_STORE
|
保存了当前系统已经使用的最大的TRX_ID,这值的管理和ROW_ID的分配类似,即每分配TRX_SYS_TRX_ID_WRITE_MARGIN(256)个TRX_ID写一次数据库。
|
TRX_SYS_FSEG_HEADER
|
这个地址是从第46Byte开始;
TRX SYSTEM 段(segment)的
头域,指向的是INODE页中的某
个inode entry的地址,这个inode
entry用于管理这个segment
|
TRX_SYS_RSEGS[]
| 这个数组是记录了所有的rollback segment 的SPACE_ID和PAGE_NO; 所有的SPACE_ID都是0,即所有的rollback segment页都是从系统空间分配的. 所有的ROLLBACK SEGMENTs在系统启动时就分配好。 |
|
|
|
|
ROLLBACK SEGMENT HEADER PAGE
|
|
TRX_RSEG_MAX_SIZE
|
Maximum allowed size for rollback Segment in pages.现在这个值是
ULINT_MAX; 在这个段管理页初始化是初始化为:
ULINT_MAX: (ulint)(-2)
|
TRX_RSEG_HISTORY_SIZE
|
已提交,但是未Purge的事务所占用的Undo Pages数量(Update/Delete操作)
|
TRX_RSEG_HISTORY
|
统一管理提交之后的Undo Log Pages;双向链表,链表项为Undo Log Header Page上的Undo Log Header(TRX_RSEG_HISTORY管理
双向链表头; 管理undo log, 即指向undo log header 的TRX_UNDO_HISTORY_NODE双向链表)
|
TRX_RSEG_FSEG_HEADER
|
回滚段的段头;指向这个段的inode entry.
|
TRX_RSEG_UNDO_SLOTS
|
当前回滚段,包含的Undo Slots数组的起始位置;TRX_RSEG_N_SLOTS (UNIV_PAGE_SIZE / 16):1024个Undo Slots;每个段头页,维护1024个Undo Slots;
在一个事务中,当需要进行写一个UNDO LOG时,就申请一个
TRX_RSEG_UNDO_SLOTS.
|
UNDO LOG SEGMENT PAGE
|
NORMAL UNDO LOG PAGE只有
TRX_UNDO_PAGE_HDR,而没有UNDO LOG HEADER
|
TRX_UNDO_PAGE_HDR_SIZE
| 下面4个字段是TRX_UNDO_PAGE_HDR, 用于管理本UNDO LOG SEGMENT PAGE的使用情况 |
TRX_UNDO_PAGE_TYPE
| 表示当前的UNDO LOG SEGMENT PAGE 是用作插入(TRX_UNDO_INSERT)还是更新(TRX_UNDO_UPDATE) |
TRX_UNDO_PAGE_START
|
下一个undo log header从这里开始; 这个值通常等于TRX_UNDO_PAGE_FREE(下一个字段,即申请一个新的UNDO LOG HEADER时,是从
TRX_UNDO_PAGE_FREE开始分配,然后同时更新这两个值);在discard undo log时和
这个不同。
【Byte offset where the undo log
records for the LATEST transaction
start on this page (remember that
in an update undo log, the first page
can contain several undo logs)】
|
TRX_UNDO_PAGE_FREE
|
记录本页空闲可以使用空间的起始地址, 当要用一个UNDO LOG HEADER时,可以从这个地址开始申请空间。【On each page of the undo log this
field contains the byte offset of the
first free byte on the page】
|
TRX_UNDO_PAGE_NODE
|
这个undo log segment的所有undo log页用这个双向链表链接起来,当本页(UNDO LOG SEGMENT PAGE)或没个NORMAL UNDO LOG PAGE的剩余空间不够时,就会申请一个
NORMAL UNDO LOG PAGE挂接到这个双向链表下,见函数trx_undo_add_page()。【The file list node in the chain of undo log pages】
|
UNDO LOG SEGMENT HEADER
|
TRX_UNDO_SEG_HDR
|
TRX_UNDO_STATE
|
TRX_UNDO_ACTIVE, ...当前undo log header的状态: TRX_UNDO_ACTIVE, TRX_UNDO_CACHED, TRX_UNDO_TO_FREE, TRX_UNDO_TO_PURGE, TRX_UNDO_PREPARED
|
TRX_UNDO_LAST_LOG
|
Offset of the last undo log header
on the segment header page, 0 if
none
|
TRX_UNDO_FSEG_HEADER
(FSEG_HDR_SPACE; FSEG_HDR_PAGE_NO; FSEG_HDR_OFFSET)
|
Header for the file segment which
the undo log segment occupies. 即这个UNDO LOG SEGMENT对应的INODE INTRY所在的SPACE_ID, PAGE_NO和INODE ENTRY在页中的偏移,即用于管理UNDO SEGMENT的簇的分配.
|
TRX_UNDO_PAGE_LIST
|
这个undo log segment中所有的undo log页双向链表的链表头;
第一个是本页的TRX_UNDO_PAGE_NODE;同一事务如果第一个页不
够用时, 从这个段里申请一个页(Normal undo log page),
用这个双向链表连接起来。
|
undo log header
| 这里是第一个UNDO LOG HEADER |
TRX_UNDO_TRX_ID
|
Transaction id,写当前的UNDO LOG的事务ID
|
TRX_UNDO_TRX_NO
|
Transaction number of the
transaction; defined only if the log
is in a history list.
这个字段来之于trx_struct->no: 这个记录了事务提交时当前的trx_sys->max_trx_id,即事务提交的时候
获取一个系统的TRX_ID, 用这个值就可以判断当前事务undo等时,可以判断其他
事务是否已经提交,没开始, 还是正在处理; 见代码trx_struct->no的注释.
|
TRX_UNDO_DEL_MARKS
|
Defined only in an update undo
log: TRUE if the transaction may have
done delete markings of records, and
thus purge is necessary.
|
TRX_UNDO_LOG_START
|
本UNDO LOG HEADER页的log数据的开头偏移,即真正log内容的起始偏移;
Offset of the first undo log record
of this log on the header page; purge
may remove undo log record from the
log start, and therefore this is not
necessarily the same as this log
header end offset.
|
TRX_UNDO_XID_EXISTS
|
TRUE if undo log header includes
X/Open XA transaction identification
XID
|
TRX_UNDO_DICT_TRANS
|
TRUE if the transaction is a table
create, index create, or drop
transaction: in recovery
the transaction cannot be rolled back
in the usual way: a 'rollback' rather
means dropping the created or dropped
table, if it still exists
|
TRX_UNDO_TABLE_ID
|
Id of the table if the preceding
field is TRUE
|
TRX_UNDO_NEXT_LOG
|
记录下一个UNDO LOG HEADER在本页的偏移【Offset of the next undo log header
on this page, 0 if none】
|
TRX_UNDO_PREV_LOG
|
记录前一个UNDO LOG HEADER在本页的偏移。Offset of the previous undo log
header on this page, 0 if none
|
TRX_UNDO_HISTORY_NODE
|
当If the log is put to the history
list, the file list node is here.
|
TRX_UNDO_XA_FORMAT
|
|
TRX_UNDO_XA_TRID_LEN
|
|
TRX_UNDO_XA_BQUAL_LEN
|
|
TRX_UNDO_XA_XID
|
|