日志
为什么 MySQL InnoDB 存储引擎默认隔离级别是 RR,而不像大多数数据库如 Oracle 使用 READ COMMITTED?这与 binlog_format 参数相关,该参数决定了二进制日志的格式。
可设定的参数值:
- STATEMENT,记录 SQL 语句
- ROW,记录行的更改情况,将 binlog 格式设置为 ROW 之后可以将 InnoDB 隔离级别设置为 READ COMMITTED
- MIXED,混合以上两种格式,在一些情况下会使用 ROW,比如使用了不确定函数时
ROW 对磁盘空间的消耗非常严重,而主从复制的网络开销也会增加。
binlog 是二进制格式的文件,只能用 mysqlbinlog 工具查看。
binlog STATEMENT 格式是按照事务的提交顺序写的,而 RC 级别因为不像 RR 级别有间隙锁,可以在另外一个事务提交之前影响该事务对数据更新的结果,并抢先提交,导致主机上 SQL
语句的执行和 binlog 记录的执行顺序不同而出现主从数据不一致。
锁
行锁的三种算法:
- Record lock,单行记录上的锁
- Gap lock,间隙锁,不包含记录本身
- Next-key lock,锁定一个范围,并且锁定记录本身
对于非唯一键进行的锁定是 Next-key lock,会将行记录本身以及左右两侧的范围都锁住;
而对于具有唯一属性的索引,利用该索引进行查询时,会降级为行锁 Record lock,提高并发性。
间隙锁如何解决RR级别下的幻读
间隙锁阻止了多个事务将记录插入到同一范围内,也就是说只要有一个事务通过某个索引节点中的某个索引数据访问了叶子结点的数据,那么该行数据以及该索引两侧间隙都会被加锁,防止其他事务修改、删除或者插入数据,防止不可重复读和幻读。
索引
InnoDB 的数据是按照索引来组织的,合并了数据文件与索引文件,B+树的每个索引节点的的索引数据根据主键进行排序。
而如果单独建立一个辅助索引,会出现一棵独立的B+树,其叶子节点的数据为主键值,利用辅助索引访问数据时需要先从辅助索引叶子节点找到主键值,再到主键索引中找到数据,会引发更多的磁盘IO。