JPA 的全称是 Java Persistence API, 即 Java 持久化 API,是一套基于 ORM 的规范,内部是由一系列的接口和抽象类构成(类似JDBC,但是需要底层的ORM框架去增强实现具体的数据库持久化操作)
核心类 EntityManager–实体管理器,提供实体类的DML、DQL方法对应于不同数据库表的DML、DQL操作
JPA 通过 JDK 5.0 及以上提供的注解描述对象-关系表映射关系,并将运行期的实体对象持久化到数据库中
JDBC与JPA的区别
1.操作的对象不一样,且使用的技术也不相同,比如JDBC通过封装JDBC接口进而通过数据库连接池等技术操作DataSource进行持久化;JPA通过增强实现JPA的ORM,操作EntityManager进行持久化
2.项目中引入的jar包不同,前者是Spring JDBC 后者是 Spring ORM
1.吞吐与延迟 :指导我们关注什么
2.没有量化就没有改进:监控与度量指标,指导我们怎么去入手
3.80/20原则:先优化性能瓶颈问题,关键的少数问题导致了大部分的性能问题,指导我们如何去优化
4.过早的优化是万恶之源:指导我们要选择优化的时机
5.脱离场景谈性能都是耍流氓:指导我们对性能要求要符合实际
1.第一范式(1NF):表里面的每一个字段都不可以继续拆分成多个字段
2.第二范式(2NF):表里面的非主键字段不能不依赖于主键字段或者是只依赖于联合主键的部分字段
3.第三范式(3NF):消除传递依赖,非主键字段除了依赖主键,不能再依赖于非主键字段
4.BC 范式(BCNF):主要针对联合主键,联合主键可能导致数据插入不成功,因为关键业务数据缺少联合主键中的部分字段,这说明该表对于改业务而言可以继续拆分为多张表,减少联合主键包含的字段
5.第四范式(4NF):消除非平凡的多值依赖&第五范式(5NF):消除一些不合适的连接依赖
1.开源:MySQL、PostgreSQL
2.商业:Oracle,DB2,SQL Server
3.内存数据库:Redis(严格算不上数据库因为会造成数据丢失),VoltDB
4.图数据库:Neo4j,Nebula
5.时序数据库:InfluxDB、openTSDB
6.其他关系数据库:Access、Sqlite、H2、Derby、Sybase、Infomix 等
7.NewSQL/分布式数据库:TiDB、CockroachDB、NuoDB、OpenGauss、OB、TDSQL
NoSQL 数据库:MongoDB、Hbase、Cassandra、CouchDB
Server 层包括连接器、查询缓存、分析器、优化器、执行器,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等
接器负责跟客户端建立连接、获取权限、维持和管理连接
连接命令一般是这么写的:
mysql -h -P -u -p
[mysql ]: 是客户端工具
[-h]: 表示后面跟着输入数据库服务器的地址
[-P]: 表示后面跟着输入访问数据库服务器的端口
[-u]: 表示后面跟着需要输入用户名
[-p]: 表示敲完回车后面跟着输入访问数据库服务器的端口
用户名、密码认证通过,连接器会到权限表里面查出你拥有的权限。之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限,即为一次查询,一直使用,只有再新建的连接才会使用新的权限设置
1、空闲连接:连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,通过show processlist
命令查看所有连接,其中如图所示command列为“sleep”的即为空闲连接
客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout
控制的,默认值是 8 小时
2、长连接:指连接成功后,如果客户端持续有请求,则一直使用同一个连接
3、短连接:每次执行完很少的几次查询就断开连接,下次查询再重新建立一个
建立连接的过程通常是比较复杂的,建议使用长连接
MySQL 在执行过程中临时使用的内存是由创建的连接对象管理、划分、使用的,如果长连接累积下来,可能导致内存占用太大,被系统强行杀掉(OOM,全称“Out Of Memory”
),从现象看就是 MySQL 异常重启了
解决由连接数过多导致的MySQL异常重启:
1、定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存大的查询后,断开连接,之后要查询再重连
2、MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection
来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态
MySQL 拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果
优点:如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高
缺点:查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空
MySQL 8.0 版本直接将查询缓存的整块功能删掉了
将参数 query_cache_type
设置成 DEMAND
,这样对于默认的 SQL 语句都不使用查询缓存。而对于确定要使用查询缓存的语句,可以用 SQL_CACHE
显式指定,像下面这个语句一样:
Select SQL_CACHE * from T where ID=10;
如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证,验证的是针对该表的查询权限
当查询缓存未命中,则开始执行语句,分析器负责解析SQL语句判断需要做什么,以及检查语法和涉及到的表与字段
先判断一下你对这个表有没有执行相应操作的权限,如果没有,就会返回没有权限的错误,但是对于存储过程、视图等是无法检查的,必须要在执行器执行前进行检查
经过了分析器,MySQL 就知道要做什么了,优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序
MySQL 通过分析器知道了你要做什么,通过优化器知道了该怎么做,于是就进入了执行器阶段,开始执行语句
开始执行的时候,要先判断一下你对这个表有没有执行相应操作的权限,如果没有,就会返回没有权限的错误,这是最终的权限检查,主要检查Precheck无法检查的如视图、存储过程等
如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口
information_schema
是 MySQL 系统自带的数据库,主要保存 MySQL 数据库服务器的系统信息,比如数据库的名称、数据表的名称、字段名称、存取权限、数据文件 所在的文件夹和系统使用的文件夹,等等performance_schema
是 MySQL 系统自带的数据库,可以用来监控 MySQL 的各类性能指标。sys
数据库是 MySQL 系统自带的数据库,主要作用是以一种更容易被理解的方式展示 MySQL 数据库服务器的各类性能指标,帮助系统管理员和开发人员监控 MySQL 的技术性能。mysql
数据库保存了 MySQL 数据库服务器运行时需要的系统信息,比如数据文件夹、当前使用的字符集、约束检查信息、用户,等等用户创建的数据库所在目录主要看安装时的设置,上图路径时默认路径
innodb_file_per_table=OFF/ON
数据库中的所有schema中的table相关文件都在 ibdata1、ibdata2…等系统表空间中
1.from、on、join:按照次序主要是为了找到涉及到的Table
2.where、group by、having+聚合函数:按照次序主要是为了对前面找到的所有表的记录进行过滤Filter
3.select、order by、limit:按照次序主要是为了将满足过滤条件的记录在客户端展现Show
Innodb为什么选择B+树作为数据的存储结构
1.所有数据都在叶子结点,有助于减少层数,随机IO的次数就更少
2.叶子结点之间组成双向链表,对于遍历和范围查询效率更高
3.使用自增主键,能够减少叶分裂导致的计算消耗,提高存储数据的速度
数据是按页来分块的,一个数据块就是一个数据页(树结点),当一个数据被用到时,其附近的数据也通常会马上被使用,InnoDB 使用 B+ 树实现聚集索引
对于InnoDB 而言聚集索引(聚簇索引)也是主键索引,如下图B+树就是聚簇索引,每一个节点就一个数据块,叶子结点存储了多个主键索引所在行的全部记录信息,并且叶子结点之间有的关系可以看成是双向节点,这样可以方便的存取数据
一张Innodb表只能有一个聚簇索引,聚簇索引叶子结点的数据顺序就是数据的物理存储顺序
主键索引的更新
替换更新
非主键索引的更新
删除+新建
Myisam默认的锁级别是表锁,innodb默认的锁级别是行锁
Myisam的存储文件中的索引文件仅存储了 索引+对应记录的存储地址,innodb因为一定会使用聚簇索引,所以数据和索引是一同保存为.ibd的数据文件中的,并且数据的存储结构和聚簇索引相一致
当使用select count(*)查询表中记录数时,Myisam可以直接返回,因为使用该引擎的的表会统计并存储表中记录数,innodb需要遍历主键索引树
innodb由于需要支持事务引入了MVCC,这就导致了不同事务查寻到的记录条数是不同的
row_id是innoDB中维护的一个全局变量
dictsys.row_id
,没有定义主键的表都会共享使用这个row_id,在插入数据时会把这个全局row_id当作自己的主键,然后再将这个全局变量加 1
2^(申请自增Id次数-1)
的数量分配自增Id,所以前一次事务未能使用完的自增Id,在下一次事务中只能使用以此为基础+1的自增Id、5.自增的步长不为1时,自增Id也是不连续的在应用 redo log 时,需要先从double write缓存中得到一个目标数据页的副本用于还原数据页,然后再重做,这也是double write的意思
- innodb 会监控对表上的二级索引的查询情况,对于满足条件的二级索引数据,如果观察到建立哈希索引后能够带来速度提升,则会自动生成对应的哈希索引,所以被称为自适应哈希索引
- 自适应哈希索引使用buffer pool构建B+树来构造,所以速度会非常快
- 线性预读以extent为单位,用于将下一个extent提前读取到buffer pool中
- 随机预读以extent中的page为单位,用于将extent中剩余的page提前读取到buffer pool中
show schemas
--显示所有数据库create schema 'my_Schemas'
--创建名为my_Schemas
的数据库use 'my_Schemas'
–使用/切换当前数据库为'my_Schemas'
show variables like '%dir%'
--查看数据库所有的目录,basedir
这一项指向了MySQL的安装目录,datadir
这一项指向了MySQL各个数据库文件的存储目录(无论是独占还是共享存储模式)show variables like '%port%'
--查看数据库使用的所有端口show variables like '%version%'
–查看数据库相关所有版本号create table test_1(
id int not null,primary key(
id))engine=InnoDB default charset=utf8mb4
--在当前数据库创建表名为 test_1
的建表语句show tables
--查看当前数据库所有的表show create table 'test_1'
--查看名为 test_1
的表的建表语句show columns from 'test_1'
--查看表名为 test_1
的所有列;explain
这个命令来查看一个这些SQL语句的执行计划,就是为了分析耗时,是否走索引。在Oracle中是explain plan for
命令查看索引执行计划performance_schema
的启用和关闭mysql-cli 或 IDE(DataGrip,MySQL-WorkBench,MySQL-Front,Navicat 等)
show variables like '%xxx%'
--模糊查询配置变量名包含xxx
的所有配置参数show variables like ‘xxx’
or select @@xxx
--查看配置变量名为xxx
配置参数global
开头或包含global
单词show global variables like '%xxx%'
or show glob variables like 'xxx'
or select @@xxx
set xxx=aaa
or set global.xxx=aaa
,有些参数是只读的不能修改max_connections
最大连接数back_log
等待MySQL接受的新连接请求数wait_timeout
等待超时的时间 和 interative_timeout
交互状态下的超时时间,对于超时的连接会被断开,早期的连接池不会自动重连和test连接,现在的连接池基本都实现了重连和test连接key_buffer_size
这个参数只针对MyISAM存储引擎,用于设置存储索引的缓存区大小决定了索引操作的速度query_cache_size
(查询缓存简称 QC)这个参数只针对server端的缓存而非存储引擎端的,MySQL8.0及以后的版本已经去掉了max_connect_errors
设置连接建立过程中发生错误的最大连接数sort_buffer_size
设置排序缓存区大小,默认只有1Mmax_allowed_packet=32M
设置允许向MySQL发送的数据的最大的大小join_buffer_size=2M
设置连接表时用到的连接缓存区大小thread_cache_size=300
设置线程的缓存大小innodb_buffer_pool_size=128M
设置存储 使用索引的查询 的缓存区大小,存储内容同时包括索引和对应的记录innodb_flush_log_at_trx_commit
设置提交事务的时候将 redo 日志写入磁盘中的策innodb_thread_concurrency=0
设置并发线程数innodb_log_buffer_size
设置日志的缓存区大小innodb_log_file_size=50M
设置日志文件的大小innodb_log_files_in_group=3
设置日志组中的日志文件数目,推荐是3read_buffer_size=1M
设置读取数据的时候缓存区大小read_rnd_buffer_size=16M
设置随机读数据的时候缓存区大小bulk_insert_buffer_size=64M
设置批量插入的缓存区大小binary log
设置bin log相关的参数,有很多1.隐式的数据转换
2.慢查询
rows_examined
表示一个查询语句执行过程中扫描了多少行,这个值就是在执行器每次调用引擎获取数据行的时候累加的(扫描行数=在索引树上取数据的次数 )3.索引相关
4.写入优化
insert into xxx values (a,a,a),(b,b,b)...
,这种方式就是Multiple Values,或者通过PreparedStatement的Add Batch,JDBC可以通过特定参数实现Multiple Values5.数据更新优化
6.模糊查询优化
7.连接查询优化
8.索引失效优化
is null
,则只能出现一次,最好是直接将数据库字段定义为not null9.大查询SQL优化
limit 1000000 10
即offset=1000000
、size=10
,表示在最后查出来的结果集中前1000000 条记录抛弃,只取后面10条offset
次的回表,且查询的字段越多,意味着单条记录所占内存越大,就浪费了越多MySQL服务器的内存用于存放最终要被舍弃的记录,而且查询速度降低offset
条记录,然后主查询在此基础上再往后取size
条记录
- 上图锁兼容性都是建立在表级锁的级别,S、X可以是表级锁也可以是行级锁,具体是表级锁还是行级锁需要看SQL是否使用索引以及涉及到的范围
- S锁是通过SQL手动加的:
select * from table_name lock in share mode;
- X锁可以是SQL手动加:
select * from table_name for update;
,也可以是自动加,自动加的时候是因为update
或delete
(记录锁、临键锁、间隙锁都是排它锁的一种)- IX与S冲突的前提是,隔离级别为非RC且IX产生的原因为DML(半一致性读的优化避免了冲突),而非
for update
flush tables with read lock;
(FTWRL))、DDL(添加元数据锁(MateDataSource Lock,MDL))时1.记录锁(Record): 锁定索引对应记录
2.间隙锁(Gap): 锁住一个范围
3.临键锁(Next-Key): 记录锁+间隙锁的组合
4.谓词锁(Predicat): 空间索引
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id = 1 for update;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | 路飞 | 19 |
+----+--------+-----+
1 row in set (0.02 sec)
2.等值查询且记录不存在
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id = 2 for update;
Empty set (0.03 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id > 15 for update;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 20 | 香克斯 | 39 |
+----+-----------+-----+
1 row in set (0.01 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id >= 15 for update;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 15 | 乌索普 | 20 |
| 20 | 香克斯 | 39 |
+----+-----------+-----+
2 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id < 6 for update;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | 路飞 | 19 |
| 5 | 索隆 | 21 |
+----+--------+-----+
3 rows in set (0.00 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where id <= 5 for update;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | 路飞 | 19 |
| 5 | 索隆 | 21 |
+----+--------+-----+
2 rows in set (0.00 sec)
select * from user where id < 5 for update;
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where age = 22 for update;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 10 | 山治 | 22 |
+----+--------+-----+
1 row in set (0.00 sec)
当查询的记录「存在」时,由于不是唯一索引,所以肯定存在索引值相同的记录,于是非唯一索引等值查询的过程是一个扫描的过程,直到扫描到第一个不符合条件的二级索引记录就停止扫描,然后在扫描的过程中,对扫描到的二级索引记录加的是 next-key 锁,而对于第一个不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁。同时,在符合查询条件的记录的主键索引上加记录锁
2.等值查询且记录不存在
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where age = 25 for update;
Empty set (0.00 sec)
当查询的记录「不存在」时,扫描到第一条不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁。因为不存在满足查询条件的记录,所以不会对主键索引加锁
3.范围查询
非唯一索引和主键索引的范围查询的加锁类似,只是范围不同
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from user where age >= 22 for update;
+----+-----------+-----+
| id | name | age |
+----+-----------+-----+
| 10 | 山治 | 22 |
| 20 | 香克斯 | 39 |
+----+-----------+-----+
2 rows in set (0.01 sec)
二级索引的间隙锁,区间的端点记录是否允许插入同样索引值的记录,还需要看端点记录对应的主键,因为二级索引值相同的情况下,是按照主键值排序的,意味着插入与间隙锁端点记录同样的二级索引值记录有可能因为主键值更小或更大而不在间隙锁的区间内,所以可以插入
MyISAM 中是不会产生死锁的,因为 MyISAM 总是一次性获得所需的全部锁,要么全部满足,要么全部等待
读未提交
读已提交
4.会产生:不可重复读、幻读(Phantom)
5.默认情况下只有记录锁
SHOW ENGINE INNODB STATUS \G;
select * from performance_schema.data_locks;
show variables like '%isolation%';
select @@tx_isolation;
、show variables like 'transaction_isolation';
select @@global.tx_isolation;
set session transaction isolatin level 隔离级别;
set global transaction isolation level 隔离级别;
使用其他方式的优点是避免了前面三种方式造成的唯一ID连续问题,连续的序列号作为唯一ID有可能会泄露业务的数据规模
1.分页插件
2.其他手段
innodb_flush_log_at_trx_commit
这个参数设置成 1 的时候,表示每次事务的 redo log 都直接持久化到磁盘
innodb_flush_log_at_trx_commit={0|1|2}
指定何时将事务日志刷到磁盘,默认为1
innodb_flush_log_at_trx_commit=0
的情况innodb_log_file_size
决定的,默认是48MBinnodb_log_file_in_group
决定的当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log里面,并更新内存(如果此时涉及到的数据页已经在内存就更新内存,不在内存就不更新内存而是直接记录日志),这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候(系统比较空闲 或 必要的时候),将这个操作记录更新到磁盘里面(刷脏页)
保证短时间内最近的更新能够在出现意外后能够恢复的能力
有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe
在崩溃恢复场景中,InnoDB 如果判断到一个数据页可能在崩溃恢复的时候丢失了更新,就会将它读到内存,然后让 redo log 更新内存内容。更新完成后,内存页变成脏页
redo log擦除 = flush 脏页
InnoDB 用缓冲池(buffer pool)管理内存,内存存在三种状态
在 InnoDB 中,innodb_flush_neighbors
参数就是用来控制这个行为的,值为 1 的时候会有上述的“连坐”机制,值为 0 时表示不找邻居,自己刷自己的
该功能对于机械硬盘提升比较大,因为机械硬盘IOPS比较低,对于SSD硬盘,IPOS不再是瓶颈,需要关掉,自己刷自己的效率反而更高
innodb_io_capacity
这个参数,它会告诉 InnoDB ,主机的磁盘 IO能力。这个值建议设置成磁盘的 IOPS(每秒的读写次数)。磁盘的 IOPS 可以通过 fio 这个工具来测试,下面的语句也可以用来测试磁盘随机读写IOPS: fio -filename=$filename -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest
innodb_io_capacity
越低,刷脏页的速度越慢,造成脏页的积累,导致频繁的阻塞,语句执行就会十分慢
innodb_max_dirty_pages_pct
是脏页比例上限,默认值是 75%。InnoDB 会根据当前的脏页比例(假设为 M),算出一个范围在 0 到 100 之间的数字,这个计算用F(M)表示Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total
得到的,具体的命令参考下面的代码:select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;
innodb_io_capacity
定义的能力乘以 R% 来控制刷脏页的速度最开始 MySQL 里并没有 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog 日志只能用于归档。而 InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统——也就是 redo log 来实现 crash-safe 能力
1、bin log 是 MySQL 的 Server 层实现的,所有引擎都可以使用
2、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;bin log 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”
3、redo log 是循环写的,空间固定会用完;bin log 是可以追加写入的,bin log 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志
即先有记录redo log的prepare阶段,然后才有记录完bin log后的commit阶段,核心是两个日志都记录以后再提交
因为redo log 是InnoDB引擎特有日志,如果没有二阶段提交,引擎记录redo log日志和更新记录(事务提交)应该是几乎同时发生的
1、redo log & 事务提交 → 发生异常 → binlog
此时发生异常,根据bin log恢复数据,但是距离发生异常的最近一段时间进行更新操作无法恢复
2、binlog → 发生异常 → redo log & 事务提交
此时发生异常,根据根据binlog恢复数据,但是因为发生异常未能提交变更数据,但是恢复的数据库却是变更以后的
3、有了二阶段提交:
它们有一个共同的数据字段,叫 XID
崩溃恢复的时候,会按顺序扫描 redo log:
1、如果碰到既有 prepare、又有 commit 的 redo log,就直接提交
2、如果碰到只有 parepare、而没有 commit 的 redo log,就拿着 XID 去 bin log 找对应的事务,然后判断bin log是否完整,是则直接提交,否则回滚
1、历史原因的话,那就是 InnoDB 并不是 MySQL 的原生存储引擎。MySQL 的原生引擎是 MyISAM,设计之初就有没有支持崩溃恢复。InnoDB 在作为 MySQL 的插件加入 MySQL 引擎家族之前,就已经是一个提供了崩溃恢复和事务支持的引擎了。InnoDB 接入了 MySQL 后,发现既然 binlog 没有崩溃恢复的能力,那就用 InnoDB 原有的 redo log 好了
2、功能上的原因,bin log 没有能力恢复“数据页”
如果在图中标的位置,也就是 binlog2 写完了,MySQL 发生了 crash,重启后,引擎内部事务 2 会回滚,然后应用 binlog2 可以补回来;但是对于事务 1 来说,系统已经认为提交完成了,不会再应用一次 binlog1,对于事务1的内容对应的数据页可能还在内存中并未刷脏页,此时随着crash遗失了
1、redo log 是循环写,写到末尾是要回到开头继续写的。这样历史日志没法保留,redo log 也就起不到归档的作用
2、MySQL 系统依赖于 bin log。bin log 作为 MySQL 一开始就有的功能,被用在了很多地方。其中,MySQL 系统高可用的基础,就是 bin log 复制。还有很多公司有异构系统(比如一些数据分析系统),这些系统就靠消费 MySQL 的 bin log 来更新自己的数据。关掉 bin log 的话,这些下游系统就没法输入了
general_log参考general_log的设置、作用