MySQL


MySQL事务隔离级别

事务的4种隔离级别

  • Read-uncommitted(RU):
  • Read-commited(RC):
  • Repeatable-read(RR):InnoDB默认隔离级别,并用了Next-KeyLock锁算法,不会出现幻读 通过>select @@tx_isolation命令查看
  • Serializable:InnoDB存储引擎在分布式事务时一般用的Serializable

MySQL的默认存储方式   P186

查看存储方式的命令为:>show engines
默认方式为InnoDB,是支持事务性的存储引擎

MyISAM和InnoDB区别   P187

MyISAM

  1)5.5之前默认存储方式
  2)不支持事务,效率极高,奔溃后将无法安全恢复
  3)只支持表级锁
  4)不支持外键

InnoDB

  1)5.5之后包含存储方式,5.7后为默认存储方式
  2)支持事务、回滚、奔溃修复能力的事务安全,效率慢
  3)支持行级锁(默认)和表级锁
  4)支持外键
  5)支持MVCC(多版本并发):只有写写相互阻塞,读写|写读|读读可以并行,可以使用乐观锁和悲观锁来实现

为什么InnBD使用可重复的的隔离级别?

之前老版本主要解决MySQL主从复制问题

可以发现在RR级别下,binlog为任何格式均不会造成主从数据不一致的情况出现,但是当低版本MySQL使用RC+STATEMENT组合时(MySQL5.1.5前只有statement格式)将会导致主从数据不一致。当前这个历史遗漏问题以及解决,大家可以将其设置为RC+ROW组合的方式(例如ORACLE等数据库隔离级别就是RC),而不是必须使用RR(会带来更多的锁等待),具体可以视情况选择。

MySQL归档日志binlog   

具体命令/讲解:https://baijiahao.baidu.com/s?id=1727529344670607619&wfr=spider&for=pc

1)Statement追加模式(Statement-Based Replication,SBR):每一条会修改数据的 SQL 都会记录在 binlog 中

  • 优点:Statement 模式只记录执行的 SQL,不需要记录每一行数据的变化,因此极大的减少了 binlog 的日志量,避免了大量的 IO 操作,提升了系统的性能。
  • 缺点:正是由于 Statement 模式只记录 SQL,而如果一些 SQL 中 包含了函数,那么可能会出现执行结果不一致的情况。比如说 uuid() 函数,每次执行的时候都会生成一个随机字符串,在 master 中记录了 uuid,当同步到 slave 之后,再次执行,就得到另外一个结果了。所以使用 Statement 格式会出现数据一致性问题。 

2)Row快照模式(Row-Based Replication,RBR):不记录 SQL 语句上下文信息,仅保存哪条记录被修改。

  • 优点:Row 格式的日志内容会非常清楚地记录下每一行数据修改的细节,这样就不会出现 Statement 中存在的那种数据无法被正常复制的情况。
  • 缺点:Row 格式日志量太大了,特别是批量 update、整表 delete、alter 表等操作,由于要记录每一行数据的变化,此时会产生大量的日志,大量的日志也会带来 IO 性能问题。

3)Mixed(Mixed-Based Replication,MBR):Statement 和 Row 的混合体

MySQL的索引数据结构  P188

BTree索引:(MySQL中主要是B+Tree索引)
MyISAM:叶节点的data域存放的是数据记录的地址,在检索的时候,先搜索索引,如果key存在,就取出data域的值读取数据记录。
InnoDB:叶子节点保存了完整的数据记录。在根据主索引搜索时,直接找到key所在节点取出数据;在根据辅助索引检索时需要先取主索引的值,再走一遍主索引
哈希索引:当单条记录时查询更快,对于哈希索引来说底层就是哈希表

大表优化的几个方案   P192

SQL查询规范:https://mp.weixin.qq.com/s__biz=Mzg2OTA0Njk0OA==&mid=2247485117&idx=1&sn=92361755b7c3de488b415ec4c5f46d73&chksm=cea24976f9d5c060babe50c3747616cce63df5d50947903a262704988143c2eeb4069ae45420&token=79317275&lang=zh_CN%23rd

分表(垂直分区):是将一张大表分成多个小表,垂直切分,查询时需要连表查询
表分区(水平分区):是列不变,将表中数据分到多个同样的表,查询时用union all合并查询结果
读写分离:主库负责写,从库负责读限定查询范围:分页查询

MySQL表分区

分区方式

Range分区:基于一个给定的连续区间的列值。例如:范围分区(0,100],(100,200];时间分区(2022-01-01 00:00:00,2022-01-01 23:59:59]

List分区:类似range,区别是list分区是基于一个离散值集合,对某个值进行分区。例如()

Hash分区:基于用户定义的表达式进行分区

Key分区:

创建分区的两种方式

新表创建分区

已有表且有数据时创建分区

#order为表名,order_date为列名
alter table order
partition by range(order_date)(
    partition p1 values less than (UNIX_TIMESTAMP('2020-01-01')),
    partition p2 values less than (UNIX_TIMESTAMP('2021-01-01')),
    partition pmax values less than (maxvalue)
)


一点小知识

数据库的一些命令
是否走索引查询 >explain select * from ...
查询log是否开启 >show global variables like 'log'
查询数据库的隔离级别 >select @@tx_isolation
Mysql查看日志
1)查看日志是否开启>show variables like 'log_bin'
2)如果是开启,则在日志文件就在mysql的安装目录的data目录下

delete from 表名和truncate table 表名
1)delete相当于一条一条删除,自增id会继续增加
2)truncate相当于重建表,自增id从1开始
3)truncate比delete要快,但不记录日志不可恢复数据