1,data目录与数据表文件
1)
ps aux | grep mysql
,找到数据目录
如下图,数据目录中的数据库个数与mysqlshow databases
对应。
mysql单机实例的数据目录
对于数据库中表结构
db.opt记录字符集编码和字符集排序规则。 default-character-set=utf8 default-collation=utf8_general_ci
ibd数据表的Innodb索引文件和数据文件
frm是描述表结构的文件
myisam引擎:
frm表定义; MYI索引文件;MYD 数据文件
2)InnoDB 的逻辑存储结构
3)在mysql的数据目录下,ibdata1文件。
原本是共享表空间,默认Innodb_file_per_table 参数开启,为每个表创建单独的表空间,即ibd文件。
保存了undo log、InnoDB表的元数据、Buffer。
2,MVCC实现。
1)Mutli-Version Concurreny Control,
多版本并发控制,读不加锁,读写不冲突。
应用于 Read Commited 和 Repeatable read 两个事务隔离级别。
快照读:普通的select,不加锁,读取记录的可见版本。
当前读:select...lock in share mode/for update、update、insert、delete,读取记录最新版本,并加锁。
ibd文件(又叫表空间
)中包含数据段,索引段,回滚段(undo log)
回滚段中存储undo log
,所谓的多版本数据
指的是undo log中的多条记
2)数据行结构
DB_TRX_ID:这行数据最后插入或修改的事务id
DB_ROLL_PTR:当该行数据被更新的时候,修改前的内容记录到undo log中,回滚指针指向该条undo log记录
DB_ROW_ID:表中不存主键 或者 唯一索引,那么数据库 就会采用DB_ROW_ID生成聚簇索引。
3)undo log
作用:undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer,在适合的时间把undo buffer中的内容刷新到磁盘。
存储位置:所有的undo log均存放在主ibd数据文件(表空间)中
创建时间:每次对数据进行更新操作时,copy 当前数据,保存到undo log 中,并将当前行的回滚指针指向undo log中的旧记录
4)Read View判断行的可见性
read view (主要用来判断当前版本数据的可见性。):创建一个新事务时,copy一份当前系统中的活跃事务列表。意思是,当前不应该被本事务看到的其他事务id列表。
Read Commited隔离级别判断算法
在每次语句执行的过程中,都关闭read_view, 重新创建当前的一份新的read_view。
:
read view中事务idT_min~T_max
,当前事务T1
。
...执行sql,创建一份最新的read_view;
...T1<T_min
,说明T1事务比较早,该行对当前事务T1可见。
...T1 > T_max
,说明T1比较晚,该行对当前事务不可见,根据DB_ROLL_PTR
找到上一个判断再次判断。
...T_min <= T1 <= T_max
,如果read_view中有该事务,则不可见,找上一个版本。如果不在则可见(在read commited下
)。
Repeatable read各级离别下判断算法:创建事务trx结构的时候,就生成了当前的global read view。
read committed 总是读最新一份快照数据,而repeatable read 读事务开始时的行数据版本。
5)trx_id_1< trx_id_min
那么表明该行记录所在的事务已经在本次新事务创建之前就提交了,所以该行记录的当前值是可见的。
trx_id_1>trx_id_max
的话,那么表明该行记录所在的事务在本次新事务创建之后才开启,所以该行记录的当前值不可见。通过DB_ROLL_PTR找到上一版数据判断
trx_id_min<=trx_id_<=trx_id_max, 那么表明该行记录所在事务在本次新事务创建的时候处于活动状态,从trx_id_min到trx_id_max进行遍历,如果trx_id_1等于他们之中的某个事务id的话,那么不可见。
通过DB_ROLL_PTR找到上一版数据判断`
3,实例
1)初始行
2)事务1更新操作(因为update会加排他锁X,所以undo log都是排队顺序的,不会出现两个事务并发增加undo log)
3)事务2更新操作