Skip to content

Commit 9eb6099

Browse files
committed
Update Java Notes
1 parent e78fcf4 commit 9eb6099

File tree

3 files changed

+309
-137
lines changed

3 files changed

+309
-137
lines changed

DB.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,7 +2136,7 @@ undo log 是采用段 (segment) 的方式来记录,每个 undo 操作在记录
21362136
rollback segment 称为回滚段,每个回滚段中有 1024 个 undo log segment
21372137

21382138
* 在以前老版本,只支持1个 rollback segment,只能记录 1024 个 undo log segment
2139-
* MySQL5.5 开始支持128个 rollback segment,支持 128*1024 个 undo 操作
2139+
* MySQL5.5 开始支持 128 个 rollback segment,支持 128*1024 个 undo 操作
21402140

21412141

21422142

@@ -2194,7 +2194,7 @@ redo log,记录**数据页的物理修改**,而不是某一行或某几行
21942194
InnoDB 作为存储引擎,数据是存放在磁盘中,每次读写数据都需要磁盘 IO,效率会很低。InnoDB 提供了缓存 Buffer Pool,Buffer Pool 中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲:
21952195

21962196
* 从数据库读取数据时,会首先从缓存中读取,如果缓存中没有,则从磁盘读取后放入Buffer Pool
2197-
* 向数据库写入数据时,会首先写入缓存,缓存中修改的数据会定期刷新到磁盘,这一过程称为刷脏
2197+
* 向数据库写入数据时,会首先写入缓存,缓存中修改的数据会**定期刷新**到磁盘,这一过程称为刷脏
21982198

21992199
Buffer Pool 的使用提高了读写数据的效率,但是也带了新的问题:如果 MySQL 宕机,此时 Buffer Pool 中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证,所以引入 redo log
22002200

@@ -2205,10 +2205,10 @@ Buffer Pool 的使用提高了读写数据的效率,但是也带了新的问
22052205

22062206
redo log 采用的是 WAL(Write-ahead logging,**预写式日志**),所有修改要先写入日志,再更新到 Buffer Pool,保证了数据不会因 MySQL 宕机而丢失,从而满足了持久性要求
22072207

2208-
redo log 也需要在事务提交时将日志写入磁盘,但是比将 Buffer Pool 中修改的数据写入磁盘快:
2208+
redo log 也需要**在事务提交时**将日志写入磁盘,但是比将 Buffer Pool 中修改的数据写入磁盘快:
22092209

22102210
* 刷脏是随机 IO,因为每次修改的数据位置随机,但写 redo log 是尾部追加操作,属于顺序 IO
2211-
* 刷脏是以数据页 (Page) 为单位的,MySQL 默认页大小是 16KB,一个页上的一个小修改都要整页写入,而 redo log 中只包含真正需要写入的部分,无效IO大大减少
2211+
* 刷脏是以数据页 (Page) 为单位的,MySQL 默认页大小是 16KB,一个页上的一个小修改都要整页写入,而 redo log 中只包含真正需要写入的部分,无效 IO 大大减少
22122212

22132213
刷盘策略,通过修改参数 `innodb_flush_log_at_trx_commit` 设置:
22142214

@@ -2226,11 +2226,11 @@ redo log 也需要在事务提交时将日志写入磁盘,但是比将 Buffer
22262226

22272227
MySQL中还存在 binlog(二进制日志) 也可以记录写操作并用于数据的恢复,二者的区别是:
22282228

2229-
* 作用不同:redo log 是用于 crash recovery (故障恢复),保证MySQL宕机也不会影响持久性;binlog是用于 point-in-time recovery 的,保证服务器可以基于时间点恢复数据,此外 binlog 还用于主从复制
2229+
* 作用不同:redo log 是用于 crash recovery (故障恢复),保证MySQL宕机也不会影响持久性;binlog 是用于 point-in-time recovery 的,保证服务器可以基于时间点恢复数据,此外 binlog 还用于主从复制
22302230

2231-
* 层次不同:redo log 是 InnoDB 存储引擎实现的,而 binlog 是MySQL的服务器层实现的,同时支持InnoDB和其他存储引擎,并且二进制日志先于 redo log 被记录。
2231+
* 层次不同:redo log 是 InnoDB 存储引擎实现的,而 binlog 是MySQL的服务器层实现的,同时支持 InnoDB 和其他存储引擎,并且二进制日志先于 redo log 被记录。
22322232

2233-
* 内容不同:redo log 是物理日志,内容基于磁盘的 Page;binlog的内容是二进制的,根据 binlog_format 参数的不同,可能基于SQL 语句、基于数据本身或者二者的混合(日志部分详解)
2233+
* 内容不同:redo log 是物理日志,内容基于磁盘的 Page;binlog 的内容是二进制的,根据 binlog_format 参数的不同,可能基于SQL 语句、基于数据本身或者二者的混合(日志部分详解)
22342234

22352235
* 写入时机不同:binlog 在事务提交时一次写入;redo log 的写入时机相对多元
22362236

@@ -2246,7 +2246,7 @@ MySQL中还存在 binlog(二进制日志) 也可以记录写操作并用于数
22462246

22472247
### 隔离级别
22482248

2249-
事务的隔离级别:多个客户端操作时,各个客户端的事务之间应该是隔离的,**不同的事务之间不该互相影响**,而如果多个事务操作同一批数据时,则需要设置不同的隔离级别 , 否则就会产生问题
2249+
事务的隔离级别:多个客户端操作时,各个客户端的事务之间应该是隔离的,**不同的事务之间不该互相影响**,而如果多个事务操作同一批数据时,则需要设置不同的隔离级别否则就会产生问题。
22502250

22512251
隔离级别分类:
22522252

@@ -2307,7 +2307,7 @@ MVCC 处理读写请求,可以做到在发生读写请求冲突时不用加锁
23072307

23082308
* 读-写:有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
23092309

2310-
* 写-写:有线程安全问题,可能会存在更新丢失问题
2310+
* 写-写:有线程安全问题,可能会存在丢失更新问题
23112311

23122312
MVCC 的优点:
23132313

@@ -2316,8 +2316,8 @@ MVCC 的优点:
23162316

23172317
提高读写和写写的并发性能:
23182318

2319-
* MVCC + 悲观锁:MVCC解决读写冲突,悲观锁解决写写冲突
2320-
* MVCC + 乐观锁:MVCC解决读写冲突,乐观锁解决写写冲突
2319+
* MVCC + 悲观锁:MVCC 解决读写冲突,悲观锁解决写写冲突
2320+
* MVCC + 乐观锁:MVCC 解决读写冲突,乐观锁解决写写冲突
23212321

23222322

23232323

@@ -2333,15 +2333,15 @@ MVCC 的优点:
23332333

23342334
##### 隐藏字段
23352335

2336-
实现原理主要是隐藏字段,undo日志,Read View来实现的
2336+
实现原理主要是隐藏字段,undo日志,Read View 来实现的
23372337

23382338
数据库中的每行数据,除了自定义的字段,还有数据库隐式定义的字段:
23392339

23402340
* DB_TRX_ID:6byte,最近修改事务ID,记录创建该数据或最后一次修改(修改/插入)该数据的事务ID。当每个事务开启时,都会被分配一个ID,这个ID是递增的
23412341

23422342
* DB_ROLL_PTR:7byte,回滚指针,配合 undo 日志,指向上一个旧版本(存储在 rollback segment)
23432343

2344-
* DB_ROW_ID:6byte,隐含的自增ID(**隐藏主键**),如果数据表没有主键,InnoDB会自动以 DB_ROW_ID 产生一个聚簇索引
2344+
* DB_ROW_ID:6byte,隐含的自增ID(**隐藏主键**),如果数据表没有主键,InnoDB 会自动以 DB_ROW_ID 产生一个聚簇索引
23452345

23462346
* DELETED_BIT:删除标志的隐藏字段,记录被更新或删除并不代表真的删除,而是删除位变了
23472347

@@ -2366,19 +2366,19 @@ undo log 的作用:
23662366
* 保证事务进行 rollback 时的原子性和一致性,当事务进行回滚的时候可以用 undo log 的数据进行恢复
23672367
* 用于 MVCC 快照读的数据,在 MVCC 多版本控制中,通过读取 undo log 的历史版本数据可以实现不同事务版本号都拥有自己独立的快照数据版本
23682368

2369-
undo log主要分为两种
2369+
undo log 主要分为两种
23702370

23712371
* insert undo log:事务在 insert 新记录时产生的 undo log,只在事务回滚时需要,并且在事务提交后可以被立即丢弃
23722372

23732373
* update undo log:事务在进行 update 或 delete 时产生的 undo log,在事务回滚时需要,在快照读时也需要。不能随意删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被 purge 线程统一清除
23742374

2375-
每次对数据库记录进行改动,都会将旧值放到一条undo日志中,就算是该记录的一个旧版本,随着更新次数的增多,所有的版本都会被 roll_pointer 属性连接成一个链表,把这个链表称之为**版本链**,版本链的头节点就是当前记录最新的值,链尾就是最早的旧记录
2375+
每次对数据库记录进行改动,都会将旧值放到一条undo日志中,算是该记录的一个旧版本,随着更新次数的增多,所有的版本都会被 roll_pointer 属性连接成一个链表,把这个链表称之为**版本链**,版本链的头节点就是当前记录最新的值,链尾就是最早的旧记录
23762376

23772377
<img src="https://gitee.com/seazean/images/raw/master/DB/MySQL-MVCC版本链.png" style="zoom: 80%;" />
23782378

23792379
* 有个事务插入 persion 表一条新记录,name 为 Jerry,age 为 24
23802380

2381-
* 事务1修改该行数据时,数据库会先对该行加排他锁,然后先把该行数据拷贝到 undo log 中作为旧记录,拷贝完毕后修改该行 name 为Tom,并且修改隐藏字段的事务ID为当前事务1的ID(默认为1 之后递增),回滚指针指向拷贝到 undo log 的副本记录,事务提交后,释放锁
2381+
* 事务1修改该行数据时,数据库会先对该行加排他锁,然后先把该行数据拷贝到 undo log 中作为旧记录,拷贝完毕后修改该行 name 为Tom,并且修改隐藏字段的事务ID为当前事务1的ID(默认为 1 之后递增),回滚指针指向拷贝到 undo log 的副本记录,事务提交后,释放锁
23822382
* 以此类推
23832383

23842384
purge 线程:
@@ -2402,7 +2402,7 @@ Read View 几个属性:
24022402
- m_ids:生成 Read View 时当前系统中活跃的事务 id 列表
24032403
- up_limit_id:生成 Read View 时当前系统中活跃的最小的事务 id,也就是 m_ids 中的最小值
24042404
- low_limit_id:生成 Read View 时系统应该分配给下一个事务的 id 值,m_ids 中的最大值加1
2405-
- creator_trx_id:生成该 Read View 的事务的事务id
2405+
- creator_trx_id:生成该 Read View 的事务的事务id,就是判断该id的事务能读到什么数据
24062406

24072407
creator 创建一个 Read View,进行可见性算法分析:(**解决了读未提交**
24082408

@@ -2411,7 +2411,7 @@ creator 创建一个 Read View,进行可见性算法分析:(**解决了读
24112411

24122412
* db_trx_id >= low_limit_id:该版本对应的事务 ID 大于 Read view 中当前系统的最大事务ID,则说明该数据是在当前 Read view 创建之后才产生的,对 creator 不可见
24132413
* up_limit_id <= db_trx_id < low_limit_id:判断 db_trx_id 是否在活跃事务列表 m_ids 中
2414-
* 在列表中,说明该版本对应的事务正在运行,数据不能显示
2414+
* 在列表中,说明该版本对应的事务正在运行,数据不能显示(不能读到未提交的数据)
24152415
* 不在列表中,说明该版本对应的事务已经被提交,数据可以显示
24162416

24172417

@@ -2469,12 +2469,12 @@ ID 为 0 的事务创建 Read View:
24692469

24702470
#### RC RR
24712471

2472-
Read View 用于支持RC(Read Committed,读已提交)和RR(Repeatable Read,可重复读)隔离级别的实现
2472+
Read View 用于支持 RC(Read Committed,读已提交)和 RR(Repeatable Read,可重复读)隔离级别的实现
24732473

2474-
RR、RC生成时机
2474+
RR、RC 生成时机
24752475

24762476
- RC 隔离级别下,每个快照读都会生成并获取最新的 Read View
2477-
- RR 隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View,之后的快照读获取的都是同一个Read View,所以一个事务的查询结果每次都是相同的
2477+
- RR 隔离级别下,则是同一个事务中的第一个快照读才会创建 Read View
24782478

24792479
解决幻读问题:
24802480

@@ -2483,11 +2483,11 @@ RR、RC生成时机:
24832483

24842484
RC、RR 级别下的 InnoDB 快照读区别
24852485

2486-
- 在RR级别下的某个事务的对某条记录的第一次快照读会创建一个 Read View, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,使用的是同一个Read View。
2486+
- RC 级别下的,事务中每次快照读都会新生成一个 Read View,这就是在 RC 级别下的事务中可以看到别的事务提交的更新的原因
24872487

2488-
当前事务在其他事务提交之前使用过快照读,那么以后其他事务对数据的修改都是不可见的,就算以后其他事务提交了数据也不可见;早于 Read View 创建的事务所做的修改并提交的均是可见的
2488+
- RR 级别下的某个事务的对某条记录的第一次快照读会创建一个 Read View, 将当前系统活跃的其他事务记录起来,此后在调用快照读的时候,使用的是同一个Read View,所以一个事务的查询结果每次都是相同的
24892489

2490-
- RC级别下的,事务中每次快照读都会新生成一个 Read View,这就是在 RC 级别下的事务中可以看到别的事务提交的更新的原因
2490+
当前事务在其他事务提交之前使用过快照读,那么以后其他事务对数据的修改都是不可见的,就算以后其他事务提交了数据也不可见;早于 Read View 创建的事务所做的修改并提交的均是可见的
24912491

24922492

24932493

@@ -4726,11 +4726,11 @@ CREATE INDEX idx_seller_name_sta_addr ON tb_seller(name,status,address);
47264726

47274727
#### 底层原理
47284728

4729-
索引失效一般是针对联合索引,联合索引一般由几个字段组成,排序方式是先按照第一个字段进行排序,然后排序第二个,依此类推,图示(a, b)索引,a 相等的情况下 b 是有序的
4729+
索引失效一般是针对联合索引,联合索引一般由几个字段组成,排序方式是先按照第一个字段进行排序,然后排序第二个,依此类推,图示(a, b)索引,**a 相等的情况下 b 是有序的**
47304730

47314731
<img src="https://gitee.com/seazean/images/raw/master/DB/MySQL-索引失效底层原理1.png" style="zoom:67%;" />
47324732

4733-
* 最左前缀法则:当不匹配前面的字段的时候,后面的字段都是无序的。这种无序不仅体现在叶子节点,也会导致查询时的非叶子节点也是无序的,因为索引树相当于忽略的第一个字段,就无法使用二分查找
4733+
* 最左前缀法则:当不匹配前面的字段的时候,后面的字段都是无序的。这种无序不仅体现在叶子节点,也会**导致查询时的非叶子节点也是无序的**,因为索引树相当于忽略的第一个字段,就无法使用二分查找
47344734

47354735
* 范围查询右边的列,不能使用索引,比如语句: `WHERE a > 1 AND b = 1 `,在 a 大于1的时候,b是无序的
47364736

@@ -6235,7 +6235,7 @@ binlog_format=STATEMENT
62356235
日志格式:
62366236

62376237
* STATEMENT:该日志格式在日志文件中记录的都是 SQL 语句 (statement),每一条对数据进行修改的 SQL都会记录在日志文件中,通过 mysqlbinlog 工具,可以查看到每条语句的文本。主从复制时,从库 (slave) 会将日志解析为原语句,并在从库重新执行一
6238-
* ROW:该日志格式在日志文件中记录的是每一行的数据变更,而不是记录SQL语句。比如执行SQL语句`update tb_book set status='1'`,如果是 STATEMENT,在日志中会记录一行 SQL 语句; 如果是ROW,由于是对全表进行更新,就是每一行记录都会发生变更,ROW 格式的日志中会记录每一行的数据变更
6238+
* ROW:该日志格式在日志文件中记录的是每一行的数据变更,而不是记录 SQL 语句。比如执行 SQL 语句`update tb_book set status='1'`,如果是 STATEMENT,在日志中会记录一行 SQL 语句; 如果是 ROW,由于是对全表进行更新,就是每一行记录都会发生变更,ROW 格式的日志中会记录每一行的数据变更
62396239

62406240
* MIXED:这是 MySQL 默认的日志格式,混合了STATEMENT 和 ROW两种格式。MIXED 格式能尽量利用两种模式的优点,而避开他们的缺点
62416241

0 commit comments

Comments
 (0)