mirror of https://github.com/dunwu/db-tutorial.git
update docs
parent
4043b110fc
commit
de02a6e483
Binary file not shown.
|
@ -20,8 +20,10 @@
|
|||
- [Mysql 命令](sql/mysql/mysql-cli.md)
|
||||
- [Mysql 维护](sql/mysql/mysql-ops.md)
|
||||
- [Mysql 原理](sql/mysql/mysql-theory.md)
|
||||
- :four: [Redis](nosql/redis/README.md)
|
||||
- :four: Redis
|
||||
- [Redis 快速入门](nosql/redis/redis-quickstart.md)
|
||||
- [Redis 复制](nosql/redis/Redis复制.md)
|
||||
- [Redis 哨兵](nosql/redis/Redis哨兵.md)
|
||||
|
||||
## 传送门
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div align="center"><img width="100px" src="http://dunwu.test.upcdn.net/images/others/zp.png"/></div>
|
||||
<div align="center"><img width="100px" src="http://dunwu.test.upcdn.net/images/others/zp.png!zp"/></div>
|
||||
|
||||
# DB Tutorial
|
||||
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
# redis 简介
|
||||
# Redis
|
||||
|
||||
**Redis 是一个基于内存的 key- value 数据库,也可用作缓存和消息代理。**
|
||||
|
||||
它支持多种数据类型:
|
||||
|
||||
- String
|
||||
- Hash
|
||||
- List
|
||||
- Set
|
||||
- Sorted Set
|
||||
- Bitmap
|
||||
- HyperLogLog
|
||||
- [Redis 复制](Redis复制.md)
|
||||
|
||||
## 命令行
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis 事件
|
||||
date: 2018/06/11
|
||||
date: 2018-06-11
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
@ -80,5 +80,5 @@ def main():
|
|||
从事件处理的角度来看,服务器运行流程如下:
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/Redis事件的调度与执行.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/Redis事件的调度与执行.png!zp" />
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis 事务
|
||||
date: 2018/06/11
|
||||
date: 2018-06-11
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis 发布订阅
|
||||
date: 2018/06/11
|
||||
date: 2018-06-11
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
---
|
||||
title: Redis 哨兵
|
||||
date: 2018/06/19
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
- database
|
||||
- nosql
|
||||
---
|
||||
|
||||
# Redis 哨兵
|
||||
|
||||
<!-- TOC depthFrom:2 depthTo:3 -->
|
||||
|
@ -881,3 +871,5 @@ Sentinel 所做的就是登记之前的中断调用时间,并和当前的调
|
|||
- 如果 30 秒内每件事都表现正常,将退出 TILT 模式。
|
||||
|
||||
注意某些情况下,使用许多内核提供的单调时钟 API 代替 TILT 模式。可是它仍然是不清晰的如果这是一个很好的解决方案,因为在进程只是仅仅挂起或调度很长时间没有执行的情况下,当前的系统会避免这个问题。
|
||||
|
||||
## 参考资料
|
||||
|
|
|
@ -1,145 +1,246 @@
|
|||
---
|
||||
title: Redis 复制
|
||||
date: 2018/06/19
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
- database
|
||||
- nosql
|
||||
---
|
||||
|
||||
# Redis 复制
|
||||
|
||||
<!-- TOC depthFrom:2 depthTo:3 -->
|
||||
|
||||
- [Redis 复制要点](#redis-复制要点)
|
||||
- [当主服务器不进行持久化时复制的安全性](#当主服务器不进行持久化时复制的安全性)
|
||||
- [Redis 主从复制是如何工作的](#redis-主从复制是如何工作的)
|
||||
- [部分重新同步](#部分重新同步)
|
||||
- [无磁盘复制](#无磁盘复制)
|
||||
- [配置](#配置)
|
||||
- [只读从服务器](#只读从服务器)
|
||||
- [设置从服务器到主服务器验证](#设置从服务器到主服务器验证)
|
||||
- [旧版复制功能](#旧版复制功能)
|
||||
- [同步](#同步)
|
||||
- [命令传播](#命令传播)
|
||||
- [旧版复制功能的缺陷](#旧版复制功能的缺陷)
|
||||
- [新版复制功能](#新版复制功能)
|
||||
- [部分重同步的实现](#部分重同步的实现)
|
||||
- [PSYNC 命令的实现](#psync-命令的实现)
|
||||
- [复制的实现](#复制的实现)
|
||||
- [1. 设置主从服务器](#1-设置主从服务器)
|
||||
- [2. 主从服务器建立 TCP 连接。](#2-主从服务器建立-tcp-连接)
|
||||
- [3. 发送 PING 检查通信状态。](#3-发送-ping-检查通信状态)
|
||||
- [4. 身份验证。](#4-身份验证)
|
||||
- [5. 发送端口信息。](#5-发送端口信息)
|
||||
- [6. 同步。](#6-同步)
|
||||
- [7. 命令传播。](#7-命令传播)
|
||||
- [限制有 N 个以上从服务器才允许写入](#限制有-n-个以上从服务器才允许写入)
|
||||
- [资料](#资料)
|
||||
- [Redis 复制要点](#redis-复制要点)
|
||||
- [参考资料](#参考资料)
|
||||
|
||||
<!-- /TOC -->
|
||||
|
||||
## Redis 复制要点
|
||||
## 旧版复制功能
|
||||
|
||||
- Redis 使用异步复制。但从 Redis 2.8 开始,从服务器会周期性的应答从复制流中处理的数据量。
|
||||
- 一个主服务器(master)可以有多个从服务器(slave)。
|
||||
- 从服务器也可以接受其他从服务器的连接。除了多个从服务器连接到一个主服务器之外,多个从服务器也可以连接到一个从服务器上,形成一个图状结构
|
||||
- Redis 主从复制不阻塞主服务器端。也就是说当若干个从服务器在进行初始同步时,主服务器仍然可以处理请求。
|
||||
- 主从复制也不阻塞从服务器端。当从服务器进行初始同步时,它使用旧版本的数据来应对查询请求,假设你在 redis.conf 配置文件是这么配置的。否则的话,你可以配置当复制流关闭时让从服务器给客户端返回一个错误。但是,当初始同步完成后,需要删除旧的数据集和加载新的数据集,在这个短暂的时间内,从服务器会阻塞连接进来的请求。
|
||||
- 主从复制可以用来增强扩展性,使用多个从服务器来处理只读的请求(比如,繁重的排序操作可以放到从服务器去做),也可以简单的用来做数据冗余。
|
||||
- 使用主从复制可以为主服务器免除把数据写入磁盘的消耗:在主服务器的 redis.conf 文件中配置“避免保存”(注释掉所有“保存“命令),然后连接一个配置为“进行保存”的从服务器即可。但是这个配置要确保主服务器不会自动重启(要获得更多信息请阅读下一段)
|
||||
> Redis 2.8 版本以前实现方式:`SYNC` 命令
|
||||
|
||||
## 当主服务器不进行持久化时复制的安全性
|
||||
Redis 的复制功能分为同步和命令传播两个操作:
|
||||
|
||||
在使用 Redis 复制功能时的设置中,强烈建议在 master 和在 slave 中启用持久化。当不可能启用时,例如由于非常慢的磁盘性能而导致的延迟问题,**应该配置实例来避免重置后自动重启**。
|
||||
- `同步(sync)` - 用于将从服务器的数据库状态更新至主服务器当前的数据库状态。
|
||||
- `命令传播(command propagate)` - 当主服务器的数据库状态被修改,导致主从数据库状态不一致时,让主从服务器的数据库重新回到一致状态。
|
||||
|
||||
关闭了持久化并配置了自动重启的 master 是危险的,原因如下:
|
||||
### 同步
|
||||
|
||||
- 我们设置节点 A 为 master 并关闭它的持久化设置,节点 B 和 C 从 节点 A 复制数据。
|
||||
- 节点 A 崩溃,但是他有一些自动重启的系统可以重启进程。但是由于持久化被关闭了,节点重启后其数据集合为空。
|
||||
- 节点 B 和 节点 C 会从节点 A 复制数据,但是节点 A 的数据集是空的,因此复制的结果是它们会销毁自身之前的数据副本。
|
||||
<div align="center">
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-sync.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
当在高可用系统中使用 Redis Sentinel,关闭了主服务器的持久化,并且允许自动重启,这种情况是很危险的。比如主服务器可能在很短的时间就完成了重启,以至于 Sentinel 都无法检测到这次失败,那么上面说的这种失败的情况就发生了。
|
||||
|
||||
如果数据比较重要,并且在使用主从复制时关闭了主服务器持久化功能的场景中,都应该禁止实例自动重启。
|
||||
### 命令传播
|
||||
|
||||
## Redis 主从复制是如何工作的
|
||||
同步操作完成后,主从数据库的数据库状态将达到一致。每当主服务器执行客户端发送的写命令时,主从数据库状态不再一致。需要将写命令发送给从服务器执行,使得二者的数据库状态重新达到一致。
|
||||
|
||||
如果你设置了一个从服务器,在连接时它发送了一个 SYNC 命令,不管它是第一次连接还是再次连接都没有关系。
|
||||
### 旧版复制功能的缺陷
|
||||
|
||||
然后主服务器**开始后台存储**,并且开始缓存新连接进来的修改数据的命令。**当后台存储完成后,主服务器把数据文件发送到从服务器,从服务器将其保存在磁盘上,然后加载到内存中**。然后主服务器把刚才缓存的命令发送到从服务器。这是作为命令流来完成的,并且和 Redis 协议本身格式相同。
|
||||
从服务器对主服务器的复制存在两种情况:
|
||||
|
||||
你可以通过 telnet 自己尝试一下。在 Redis 服务器工作时连接到 Redis 端口,发送 SYNC 命令,会看到一个批量的传输,并且主服务器接收的每一个命令都会通过 telnet 会话重新发送一遍。
|
||||
- 初次复制
|
||||
- 断线后重复制
|
||||
|
||||
当主从服务器之间的连接由于某些原因断开时,从服务器可以自动进行重连接。当有多个从服务器同时请求同步时,主服务器只进行一个后台存储。
|
||||
对于初次复制,旧版复制功能可用很好完成任务;但是对于断线后重复制,由于每次任然需要生成 RDB 并传输,效率很低。
|
||||
|
||||
当连接断开又重新连上之后,一般都会进行一个完整的重新同步,但是从 Redis2.8 开始,只重新同步一部分也可以。
|
||||
> :bulb: 注意:
|
||||
>
|
||||
> **SYNC 命令是一个非常耗费资源的操作。**
|
||||
>
|
||||
> 1. 主服务器执行 `BGSAVE` 命令生成 RDB 文件,这个操作会耗费主服务器大量的 CPU、内存和磁盘 I/O 资源。
|
||||
> 2. 主服务器传输 RDB 文件给从服务器,这个操作会耗费主从服务器大量的网络资源,并对主服务器响应时延产生影响。
|
||||
> 3. 从服务器载入 RDB 文件期间,会阻塞其他命令请求。
|
||||
|
||||
## 部分重新同步
|
||||
## 新版复制功能
|
||||
|
||||
从 Redis 2.8 开始,如果遭遇连接断开,重新连接之后可以从中断处继续进行复制,而不必重新同步。
|
||||
> Redis 2.8 版本以后的新实现方式:使用 `PSYNC` 命令替代 `SYNC` 命令。
|
||||
|
||||
它的工作原理是这样,**主服务器端为复制流维护一个内存缓冲区(in-memory backlog)。主从服务器都维护一个复制偏移量(replication offset)和 master run id ,当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个 master run id 相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续**。如果其中一个条件不满足,就会进行完全重新同步(在 2.8 版本之前就是直接进行完全重新同步)。因为主运行 id 不保存在磁盘中,如果从服务器重启了的话就只能进行完全同步了。
|
||||
`PSYNC` 命令具有完整重同步和部分重同步两种模式:
|
||||
|
||||
部分重新同步这个新特性内部使用 PSYNC 命令,旧的实现中使用 SYNC 命令。Redis2.8 版本可以检测出它所连接的服务器是否支持 PSYNC 命令,不支持的话使用 SYNC 命令。
|
||||
- `完整重同步(full resychronization)` - 用于初次复制。执行步骤与 `SYNC` 命令基本一致。
|
||||
- `部分重同步(partial resychronization)` - 用于断线后重复制。如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只需接收并执行这些写命令,即可将主从服务器的数据库状态保持一致。
|
||||
|
||||
## 无磁盘复制
|
||||
### 部分重同步的实现
|
||||
|
||||
通常来讲,一个完全重新同步需要在磁盘上创建一个 RDB 文件,然后加载这个文件以便为从服务器发送数据。
|
||||
部分重同步功能实现由三个部分构成:
|
||||
|
||||
如果使用比较低速的磁盘,这种操作会给主服务器带来较大的压力。Redis 从 2.8.18 版本开始尝试支持无磁盘的复制。使用这种设置时,子进程直接将 RDB 通过网络发送给从服务器,不使用磁盘作为中间存储。
|
||||
- 复制偏移量(replication offset)
|
||||
- 复制积压缓冲区(replication backlog)
|
||||
- 服务器的运行 ID
|
||||
|
||||
这一特性目前只是实验性的。
|
||||
它的工作原理是这样:**主服务器端为复制流维护一个内存缓冲区(in-memory backlog)。主从服务器都维护一个复制偏移量(replication offset)和 master run id ,当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个 master run id 相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续**。如果其中一个条件不满足,就会进行完全重新同步(在 2.8 版本之前就是直接进行完全重新同步)。
|
||||
|
||||
## 配置
|
||||
<div align="center">
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-replication-offset.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
主从复制的配置十分简单:把下面这行加入到从服务器的配置文件中即可。
|
||||
#### 复制偏移量
|
||||
|
||||
主服务器和从服务器会分别维护一个复制偏移量。
|
||||
|
||||
如果主从服务器的复制偏移量相同,则说明二者的数据库状态一致;反之,则说明二者的数据库状态不一致。
|
||||
|
||||
#### 复制积压缓冲区
|
||||
|
||||
复制积压缓冲区会保存一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量。
|
||||
|
||||
当从服务器断线重连主服务时,从服务器会通过 PSYNC 命令将自己的复制偏移量 offset 发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作。
|
||||
|
||||
- 如果 offset 之后的数据仍然在复制积压缓冲区,则主服务器对从服务器执行部分重同步操作。
|
||||
- 反之,则主服务器对从服务器执行完整重同步操作。
|
||||
|
||||
复制积压缓冲区是由主服务器维护的一个固定长度的先进先出队列,默认大小为 1MB。
|
||||
|
||||
> 注意:合理调整复制积压缓冲区的大小
|
||||
>
|
||||
> Redis 复制积压缓冲区默认大小为 1MB。
|
||||
>
|
||||
> 复制积压缓冲区的最小大小可以根据公式 `second * write_size_per_second` 估算。
|
||||
|
||||
#### 服务器的运行 ID
|
||||
|
||||
- 每个 Redis 服务器,都有运行 ID,用于唯一识别身份。
|
||||
- 运行 ID 在服务器启动时自动生成,由 40 个随机的十六进制字符组成。例如:132e358005e29741f8d7b0a42d666aace286edda
|
||||
|
||||
从服务器对主服务器进行初次复制时,主服务器会将自己的运行 ID 传送给从服务器,从服务器会将这个运行 ID 保存下来。
|
||||
|
||||
当从服务器断线重连一个主服务器时,从服务器会发送之前保存的运行 ID:
|
||||
|
||||
- 如果保存的运行 ID 和当前主服务器的运行 ID 一致,则说明从服务器断线之前连接的就是这个主服务器,主服务器可以继续尝试执行部分重同步操作;
|
||||
- 反之,若运行 ID 不一致,则说明从服务器断线之前连接的不是这个主服务器,主服务器将对从服务器执行完整重同步操作。
|
||||
|
||||
### PSYNC 命令的实现
|
||||
|
||||
<div align="center">
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-psync-workflow.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
## 复制的实现
|
||||
|
||||
### 1. 设置主从服务器
|
||||
|
||||
配置一个从服务器非常简单, 只要在配置文件中增加以下的这一行就可以了:
|
||||
|
||||
```
|
||||
slaveof 192.168.1.1 6379
|
||||
```
|
||||
|
||||
当然你需要把其中的 192.168.1.1 6379 替换为你自己的主服务器 IP(或者主机名 hostname)和端口。另外你可以调用 SLAVEOF 命令,主服务器就会开始与从服务器同步。
|
||||
当然, 你需要将代码中的 `192.168.1.1` 和 `6379` 替换成你的主服务器的 IP 和端口号。
|
||||
|
||||
关于部分重新同步,还有一些针对复制内存缓冲区的优化参数。查看 Redis 介质中的 Redis.conf 示例获得更多信息。
|
||||
另外一种方法是调用 [SLAVEOF host port](http://redisdoc.com/replication/slaveof.html#slaveof) 命令, 输入主服务器的 IP 和端口, 然后同步就会开始:
|
||||
|
||||
使用 repl-diskless-sync 配置参数来启动无磁盘复制。使用 repl-diskless-sync-delay 参数来配置传输开始的延迟时间,以便等待更多的从服务器连接上来。查看 Redis 介质中的 Redis.conf 示例获得更多信息。
|
||||
|
||||
## 只读从服务器
|
||||
|
||||
从 Redis 2.6 开始,从服务器支持只读模式,并且是默认模式。这个行为是由 Redis.conf 文件中的 slave-read-only 参数控制的,可以在运行中通过 CONFIG SET 来启用或者禁用。
|
||||
|
||||
只读的从服务器会拒绝所有写命令,所以对从服务器不会有误写操作。但这不表示可以把从服务器实例暴露在危险的网络环境下,因为像 DEBUG 或者 CONFIG 这样的管理命令还是可以运行的。不过你可以通过使用 rename-command 命令来为这些命令改名来增加安全性。
|
||||
|
||||
你可能想知道为什么只读限制还可以被还原,使得从服务器还可以进行写操作。虽然当主从服务器进行重新同步或者从服务器重启后,这些写操作都会失效,还是有一些使用场景会想从服务器中写入临时数据的,但将来这个特性可能会被去掉。
|
||||
|
||||
## 设置从服务器到主服务器验证
|
||||
|
||||
如果主服务器设置了密码,配置从服务器在所有同步中使用这个密码十分简单。
|
||||
|
||||
对于运行中的实例,使用 redis-cli 并输入:
|
||||
|
||||
```xml
|
||||
</pre>
|
||||
<pre><code>config set masterauth <password></code></pre>
|
||||
<pre>
|
||||
```
|
||||
127.0.0.1:6379> SLAVEOF 192.168.1.1 10086
|
||||
OK
|
||||
```
|
||||
|
||||
要使配置永久生效,把如下命令加入到配置文件中:
|
||||
### 2. 主从服务器建立 TCP 连接。
|
||||
|
||||
### 3. 发送 PING 检查通信状态。
|
||||
|
||||
### 4. 身份验证。
|
||||
|
||||
如果主服务器没有设置 `requirepass` ,从服务器没有设置 `masterauth`,则不进行身份验证;反之,则需要进行身份验证。如果身份验证失败,则放弃执行复制工作。
|
||||
|
||||
如果主服务器通过 `requirepass` 选项设置了密码, 那么为了让从服务器的同步操作可以顺利进行, 我们也必须为从服务器进行相应的身份验证设置。
|
||||
|
||||
对于一个正在运行的服务器, 可以使用客户端输入以下命令:
|
||||
|
||||
```xml
|
||||
</pre>
|
||||
<pre><code>masterauth <password></code></pre>
|
||||
<pre>
|
||||
```
|
||||
config set masterauth <password>
|
||||
```
|
||||
|
||||
要永久地设置这个密码, 那么可以将它加入到配置文件中:
|
||||
|
||||
```
|
||||
masterauth <password>
|
||||
```
|
||||
|
||||
另外还有几个选项, 它们和主服务器执行部分重同步时所使用的复制流缓冲区有关, 详细的信息可以参考 Redis 源码中附带的 `redis.conf` 示例文件。
|
||||
|
||||
### 5. 发送端口信息。
|
||||
|
||||
从服务器执行 `REPLCONF listening-port <port-number>` ,向主服务器发送从服务器的监听端口号。
|
||||
|
||||
### 6. 同步。
|
||||
|
||||
前文已介绍,此处不赘述。
|
||||
|
||||
### 7. 命令传播。
|
||||
|
||||
在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务发送命令:
|
||||
|
||||
```
|
||||
REPLCONF ACK <replication_coffset>
|
||||
```
|
||||
|
||||
命令的作用:
|
||||
|
||||
- 检测主从服务器的网络连接状态。
|
||||
- 辅助实现 min-slave 选项。
|
||||
- 检测命令丢失。
|
||||
|
||||
## 限制有 N 个以上从服务器才允许写入
|
||||
|
||||
从 Redis 2.8 版本开始,可以配置主服务器连接 N 个以上从服务器才允许对主服务器进行写操作。但是,因为 Redis 使用的是异步主从复制,没办法确保从服务器确实收到了要写入的数据,所以还是有一定的数据丢失的可能性。
|
||||
从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。
|
||||
|
||||
这一特性的工作原理如下:
|
||||
不过, 因为 Redis 使用异步复制, 所以主服务器发送的写数据并不一定会被从服务器接收到, 因此, 数据丢失的可能性仍然是存在的。
|
||||
|
||||
- 从服务器每秒钟 ping 一次主服务器,确认处理的复制流数量。
|
||||
- 主服务器记住每个从服务器最近一次 ping 的时间。
|
||||
- 用户可以配置最少要有 N 个服务器有小于 M 秒的确认延迟。
|
||||
以下是这个特性的运作原理:
|
||||
|
||||
如果有 N 个以上从服务器,并且确认延迟小于 M 秒,主服务器接受写操作。
|
||||
- 从服务器以每秒一次的频率 PING 主服务器一次, 并报告复制流的处理情况。
|
||||
- 主服务器会记录各个从服务器最后一次向它发送 PING 的时间。
|
||||
- 用户可以通过配置, 指定网络延迟的最大值 `min-slaves-max-lag` , 以及执行写操作所需的至少从服务器数量 `min-slaves-to-write` 。
|
||||
|
||||
你可以把这看做是 CAP 原则(一致性,可用性,分区容错性)不严格的一致性实现,虽然不能百分百确保一致性,但至少保证了丢失的数据不会超过 M 秒内的数据量。
|
||||
如果至少有 `min-slaves-to-write` 个从服务器, 并且这些服务器的延迟值都少于 `min-slaves-max-lag`秒, 那么主服务器就会执行客户端请求的写操作。
|
||||
|
||||
如果条件不满足,主服务器会拒绝写操作并返回一个错误。
|
||||
你可以将这个特性看作 CAP 理论中的 C 的条件放宽版本: 尽管不能保证写操作的持久性, 但起码丢失数据的窗口会被严格限制在指定的秒数中。
|
||||
|
||||
- min-slaves-to-write(最小从服务器数)
|
||||
- min-slaves-max-lag(从服务器最大确认延迟)
|
||||
另一方面, 如果条件达不到 `min-slaves-to-write` 和 `min-slaves-max-lag` 所指定的条件, 那么写操作就不会被执行, 主服务器会向请求执行写操作的客户端返回一个错误。
|
||||
|
||||
查看 Redis 介质中的 Redis.conf 示例获得更多信息。
|
||||
以下是这个特性的两个选项和它们所需的参数:
|
||||
|
||||
## 资料
|
||||
- `min-slaves-to-write <number of slaves>`
|
||||
- `min-slaves-max-lag <number of seconds>`
|
||||
|
||||
- http://ifeve.com/redis-replication/
|
||||
详细的信息可以参考 Redis 源码中附带的 `redis.conf` 示例文件。
|
||||
|
||||
## Redis 复制要点
|
||||
|
||||
- Redis 使用异步复制。 从 Redis 2.8 开始, 从服务器会以每秒一次的频率向主服务器报告复制流(replication stream)的处理进度。
|
||||
|
||||
- 一个主服务器可以有多个从服务器。
|
||||
|
||||
- 不仅主服务器可以有从服务器, 从服务器也可以有自己的从服务器, 多个从服务器之间可以构成一个图状结构。
|
||||
|
||||
- 复制功能不会阻塞主服务器: 即使有一个或多个从服务器正在进行初次同步, 主服务器也可以继续处理命令请求。
|
||||
|
||||
- 复制功能也不会阻塞从服务器: 只要在 `redis.conf` 文件中进行了相应的设置, 即使从服务器正在进行初次同步, 服务器也可以使用旧版本的数据集来处理命令查询。
|
||||
|
||||
不过, 在从服务器删除旧版本数据集并载入新版本数据集的那段时间内, 连接请求会被阻塞。
|
||||
|
||||
你还可以配置从服务器, 让它在与主服务器之间的连接断开时, 向客户端发送一个错误。
|
||||
|
||||
- 复制功能可以单纯地用于数据冗余(data redundancy), 也可以通过让多个从服务器处理只读命令请求来提升扩展性(scalability): 比如说, 繁重的 [SORT key [BY pattern\] [LIMIT offset count] [GET pattern [GET pattern …]] [ASC | DESC] [ALPHA] [STORE destination]](http://redisdoc.com/database/sort.html#sort) 命令可以交给附属节点去运行。
|
||||
|
||||
- 可以通过复制功能来让主服务器免于执行持久化操作: 只要关闭主服务器的持久化功能, 然后由从服务器去执行持久化操作即可。
|
||||
|
||||
- 在使用 Redis 复制功能时的设置中,强烈建议在 master 和在 slave 中启用持久化。当不启用时,例如由于非常慢的磁盘性能而导致的延迟问题,**应该配置实例来避免重置后自动重启**。
|
||||
|
||||
- 从 Redis 2.6 开始, 从服务器支持只读模式, 并且该模式为从服务器的默认模式。
|
||||
- 只读模式由 `redis.conf` 文件中的 `slave-read-only` 选项控制, 也可以通过 [CONFIG SET parameter value](http://redisdoc.com/configure/config_set.html#config-set) 命令来开启或关闭这个模式。
|
||||
- 只读从服务器会拒绝执行任何写命令, 所以不会出现因为操作失误而将数据不小心写入到了从服务器的情况。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- 《Redis 设计与实现》
|
||||
- http://redisdoc.com/topic/replication.html
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis 持久化
|
||||
date: 2018/06/11
|
||||
date: 2018-06-11
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
@ -242,7 +242,7 @@ Redis 的容灾备份基本上就是对数据进行备份,并将这些备份
|
|||
### Redis 复制的启动过程
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/Redis复制启动过程.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/Redis复制启动过程.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
当多个从服务器尝试连接同一个主服务器时:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis 数据类型
|
||||
date: 2018/06/09
|
||||
date: 2018-06-09
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
@ -31,7 +31,7 @@ tags:
|
|||
## STRING
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-string.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-string.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -58,7 +58,7 @@ OK
|
|||
## LIST
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-list.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-list.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -95,7 +95,7 @@ OK
|
|||
## SET
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-set.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-set.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -142,7 +142,7 @@ OK
|
|||
## HASH
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-hash.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-hash.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -193,7 +193,7 @@ OK
|
|||
## ZSET
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-zset.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-zset.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
title: Redis
|
||||
date: 2018/06/09
|
||||
date: 2018-06-09
|
||||
categories:
|
||||
- database
|
||||
tags:
|
||||
|
@ -107,7 +107,7 @@ Redis 与 Memcached 因为都可以用于缓存,所以常常被拿来做比较
|
|||
### 2.1. STRING
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-string.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-string.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -134,7 +134,7 @@ OK
|
|||
### 2.2. LIST
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-list.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-list.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -171,7 +171,7 @@ OK
|
|||
### 2.3. SET
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-set.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-set.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -218,7 +218,7 @@ OK
|
|||
### 2.4. HASH
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-hash.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-hash.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
@ -269,7 +269,7 @@ OK
|
|||
### 2.5. ZSET
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/redis/redis-datatype-zset.png" width="400"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/redis/redis-datatype-zset.png!zp" width="400"/>
|
||||
</div>
|
||||
|
||||
命令:
|
||||
|
|
|
@ -27,11 +27,11 @@ H2 允许用户通过浏览器接口方式访问 SQL 数据库。
|
|||
2. 启动方式:在 bin 目录下,双击 jar 包;执行 `java -jar h2*.jar`;执行脚本:`h2.bat` 或 `h2.sh`。
|
||||
3. 在浏览器中访问:http://localhost:8082,应该可以看到下图中的页面:
|
||||
|
||||
<br><div align="center"><img src="https://gitee.com/turnon/images/raw/master/images/database/h2/h2-console.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/images/database/h2/h2-console.png!zp"/></div><br>
|
||||
|
||||
点击 **Connect** ,可以进入操作界面:
|
||||
|
||||
<br><div align="center"><img src="https://gitee.com/turnon/images/raw/master/images/database/h2/h2-console-02.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/images/database/h2/h2-console-02.png!zp"/></div><br>
|
||||
|
||||
操作界面十分简单,不一一细说。
|
||||
|
||||
|
@ -263,184 +263,184 @@ java -jar h2-1.3.168.jar -web -webPort 8090 -browser
|
|||
|
||||
### SELECT
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a3f90c0d1f1f3437.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a3f90c0d1f1f3437.png"/></div><br>
|
||||
|
||||
### INSERT
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6a92ae4362c3468a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6a92ae4362c3468a.png"/></div><br>
|
||||
|
||||
### UPDATE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-dddf0e26995d46c3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-dddf0e26995d46c3.png"/></div><br>
|
||||
|
||||
### DELETE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-96e72023445a6fd6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-96e72023445a6fd6.png"/></div><br>
|
||||
|
||||
### BACKUP
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6267894d24fab47f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6267894d24fab47f.png"/></div><br>
|
||||
|
||||
### EXPLAIN
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bbed6bb69f998b7a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bbed6bb69f998b7a.png"/></div><br>
|
||||
|
||||
7、MERGE
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bd021648431d12a7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bd021648431d12a7.png"/></div><br>
|
||||
|
||||
### RUNSCRIPT
|
||||
|
||||
运行 sql 脚本文件
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d6fe03eff0037e14.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d6fe03eff0037e14.png"/></div><br>
|
||||
|
||||
### SCRIPT
|
||||
|
||||
根据数据库创建 sql 脚本
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-9ba7547ab8bcaeab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-9ba7547ab8bcaeab.png"/></div><br>
|
||||
|
||||
### SHOW
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-67449c6cc5cbb8c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-67449c6cc5cbb8c1.png"/></div><br>
|
||||
|
||||
### ALTER
|
||||
|
||||
#### ALTER INDEX RENAME
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-230bd3f97e185d2f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-230bd3f97e185d2f.png"/></div><br>
|
||||
|
||||
#### ALTER SCHEMA RENAME
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-797a028938e46ba3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-797a028938e46ba3.png"/></div><br>
|
||||
|
||||
#### ALTER SEQUENCE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-46f343da1b6c6a29.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-46f343da1b6c6a29.png"/></div><br>
|
||||
|
||||
#### ALTER TABLE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-7e146a4010f2f357.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-7e146a4010f2f357.png"/></div><br>
|
||||
|
||||
##### 增加约束
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-4e5605a9c87a79cb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-4e5605a9c87a79cb.png"/></div><br>
|
||||
|
||||
##### 修改列
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-fbc1358c553e6614.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-fbc1358c553e6614.png"/></div><br>
|
||||
|
||||
##### 删除列
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-dc3b897413700981.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-dc3b897413700981.png"/></div><br>
|
||||
|
||||
##### 删除序列
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-ec83899cb8724966.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-ec83899cb8724966.png"/></div><br>
|
||||
|
||||
#### ALTER USER
|
||||
|
||||
##### 修改用户名
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a1e429c0d8ece66c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a1e429c0d8ece66c.png"/></div><br>
|
||||
|
||||
##### 修改用户密码
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-5b86f98796606e54.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-5b86f98796606e54.png"/></div><br>
|
||||
|
||||
#### ALTER VIEW
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-8832ecbc2db63a13.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-8832ecbc2db63a13.png"/></div><br>
|
||||
|
||||
### COMMENT
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-467ce031883f0020.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-467ce031883f0020.png"/></div><br>
|
||||
|
||||
### CREATE CONSTANT
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-1231c83563bfec9c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-1231c83563bfec9c.png"/></div><br>
|
||||
|
||||
### CREATE INDEX
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d66d59bd7803d5c1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d66d59bd7803d5c1.png"/></div><br>
|
||||
|
||||
### CREATE ROLE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-7df1dee098e1127b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-7df1dee098e1127b.png"/></div><br>
|
||||
|
||||
### CREATE SCHEMA
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-c485123c62c0866e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-c485123c62c0866e.png"/></div><br>
|
||||
|
||||
### CREATE SEQUENCE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-cc25860776d361ae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-cc25860776d361ae.png"/></div><br>
|
||||
|
||||
### CREATE TABLE
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-36ffc66327df8b5b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-36ffc66327df8b5b.png"/></div><br>
|
||||
|
||||
### CREATE TRIGGER
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-9a7bfa4425281213.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-9a7bfa4425281213.png"/></div><br>
|
||||
|
||||
### CREATE USER
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a1e45e308be6dac3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-a1e45e308be6dac3.png"/></div><br>
|
||||
|
||||
### CREATE VIEW
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-45c4cd516fd36611.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-45c4cd516fd36611.png"/></div><br>
|
||||
|
||||
### DROP
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-52a3562d76411811.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-52a3562d76411811.jpg"/></div><br>
|
||||
|
||||
### GRANT RIGHT
|
||||
|
||||
给 schema 授权授权
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-750e96ceff00c4ee.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-750e96ceff00c4ee.png"/></div><br>
|
||||
|
||||
给 schema 授权给 schema 授权
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-22cfd65c2ff1eea5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-22cfd65c2ff1eea5.png"/></div><br>
|
||||
|
||||
#### 复制角色的权限
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6cba2f1585fd913b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-6cba2f1585fd913b.png"/></div><br>
|
||||
|
||||
### REVOKE RIGHT
|
||||
|
||||
#### 移除授权
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-3f905669cbb331b7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-3f905669cbb331b7.png"/></div><br>
|
||||
|
||||
#### 移除角色具有的权限
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-af77f495222f1b30.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-af77f495222f1b30.png"/></div><br>
|
||||
|
||||
### ROLLBACK
|
||||
|
||||
#### 从某个还原点(savepoint)回滚
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-c71a226ac4fff913.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-c71a226ac4fff913.png"/></div><br>
|
||||
|
||||
#### 回滚事务
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-efb65c504c7d69c2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-efb65c504c7d69c2.png"/></div><br>
|
||||
|
||||
#### 创建 savepoint
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-feefdc236d4b211d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-feefdc236d4b211d.png"/></div><br>
|
||||
|
||||
## 数据类型
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-52296dd53249cdae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-52296dd53249cdae.png"/></div><br>
|
||||
|
||||
### INT Type
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-fe62e3d07eb93d11.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-fe62e3d07eb93d11.png"/></div><br>
|
||||
|
||||
## 集群
|
||||
|
||||
|
|
|
@ -69,13 +69,13 @@
|
|||
|
||||
最简单的场景是指定 Flyway 迁移到一个空的数据库。
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bb6e9f39e56ebbda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-bb6e9f39e56ebbda.png"/></div><br>
|
||||
|
||||
Flyway 会尝试查找它的 schema 历史表,如果数据库是空的,Flyway 就不再查找,而是直接创建数据库。
|
||||
|
||||
现再你就有了一个仅包含一张空表的数据库,默认情况下,这张表叫 _flyway_schema_history_。
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-410eb31c6313b389.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-410eb31c6313b389.png"/></div><br>
|
||||
|
||||
这张表将被用于追踪数据库的状态。
|
||||
|
||||
|
@ -83,17 +83,17 @@ Flyway 会尝试查找它的 schema 历史表,如果数据库是空的,Flywa
|
|||
|
||||
这些 **migrations** 将根据他们的版本号进行排序。
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d36ee07ada4efbcd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-d36ee07ada4efbcd.png"/></div><br>
|
||||
|
||||
任意 migration 应用后,schema 历史表将更新。当元数据和初始状态替换后,可以称之为:迁移到新版本。
|
||||
|
||||
Flyway 一旦扫描了文件系统或应用 classpath 下的 migrations,这些 migrations 会检查 schema 历史表。如果它们的版本号低于或等于当前的版本,将被忽略。保留下来的 migrations 是等待的 migrations,有效但没有应用。
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-99a88fea7a31a070.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-99a88fea7a31a070.png"/></div><br>
|
||||
|
||||
migrations 将根据版本号排序并按序执行。
|
||||
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-b444fef6e5c13b71.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/></div><br>
|
||||
<br><div align="center"><img src="http://upload-images.jianshu.io/upload_images/3101171-b444fef6e5c13b71.png"/></div><br>
|
||||
|
||||
## 快速上手
|
||||
|
||||
|
@ -406,7 +406,7 @@ migrations 最常用的编写形式就是 SQL。
|
|||
|
||||
为了被 Flyway 自动识别,SQL migrations 的文件命名必须遵循规定的模式:
|
||||
|
||||
<br><div align="center"><img src="https://gitee.com/turnon/images/raw/master/images/database/flyway/sql-migrations.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/images/database/flyway/sql-migrations.png!zp"/></div><br>
|
||||
|
||||
- **Prefix** - `V` 代表 versioned migrations (可配置), `U` 代表 undo migrations (可配置)、 `R` 代表 repeatable migrations (可配置)
|
||||
- **Version** - 版本号通过`.`(点)或`_`(下划线)分隔 (repeatable migrations 不需要)
|
||||
|
@ -425,7 +425,7 @@ migrations 最常用的编写形式就是 SQL。
|
|||
|
||||
为了被 Flyway 自动识别,JAVA migrations 的文件命名必须遵循规定的模式:
|
||||
|
||||
<br><div align="center"><img src="https://gitee.com/turnon/images/raw/master/images/database/flyway/java-migrations.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/images/database/flyway/java-migrations.png!zp"/></div><br>
|
||||
|
||||
- **Prefix** - `V` 代表 versioned migrations (可配置), `U` 代表 undo migrations (可配置)、 `R` 代表 repeatable migrations (可配置)
|
||||
- **Version** - 版本号通过`.`(点)或`_`(下划线)分隔 (repeatable migrations 不需要)
|
||||
|
|
|
@ -214,6 +214,24 @@ mysql> show slave status\G;
|
|||
mysql> start slave;
|
||||
```
|
||||
|
||||
(8)将 slave 服务器设为只读
|
||||
|
||||
```
|
||||
mysql> set global read_only=1;
|
||||
mysql> set global super_read_only=1;
|
||||
mysql> show global variables like "%read_only%";
|
||||
+-----------------------+-------+
|
||||
| Variable_name | Value |
|
||||
+-----------------------+-------+
|
||||
| innodb_read_only | OFF |
|
||||
| read_only | ON |
|
||||
| super_read_only | ON |
|
||||
| transaction_read_only | OFF |
|
||||
+-----------------------+-------+
|
||||
```
|
||||
|
||||
> 注:设置 slave 服务器为只读,并不影响主从同步。
|
||||
|
||||
#### 同步主节点已有数据到从节点
|
||||
|
||||
主库操作:
|
||||
|
@ -403,7 +421,7 @@ mysqldump -u <username> -p --databases <database1> <database2> ... > backup.sql
|
|||
(3)备份所有数据库
|
||||
|
||||
```
|
||||
mysqldump -u <username> -p -all-databases > backup.sql
|
||||
mysqldump -u <username> -p --all-databases > backup.sql
|
||||
```
|
||||
|
||||
恢复:
|
||||
|
|
|
@ -283,13 +283,13 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。
|
|||
主索引的叶子节点 data 域记录着完整的数据记录,这种索引方式被称为聚簇索引。因为无法把数据行存放在两个不同的地方,所以一个表只能有一个聚簇索引。
|
||||
|
||||
<div align="center">
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-28ea7c1487bd12bb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-28ea7c1487bd12bb.png"/>
|
||||
</div>
|
||||
|
||||
辅助索引的叶子节点的 data 域记录着主键的值,因此在使用辅助索引进行查找时,需要先查找到主键值,然后再到主索引中进行查找。
|
||||
|
||||
<div align="center">
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-96c6c85468df0f89.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-96c6c85468df0f89.png"/>
|
||||
</div>
|
||||
|
||||
##### B Tree 原理
|
||||
|
@ -297,7 +297,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。
|
|||
###### B-Tree
|
||||
|
||||
<div align="center">
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-5594de9a48e524e7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-5594de9a48e524e7.png"/>
|
||||
</div>
|
||||
|
||||
定义一条数据记录为一个二元组 [key, data],B-Tree 是满足下列条件的数据结构:
|
||||
|
@ -313,7 +313,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。
|
|||
###### B+Tree
|
||||
|
||||
<div align="center">
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-b5a68f67743141a1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-b5a68f67743141a1.png"/>
|
||||
</div>
|
||||
|
||||
与 B-Tree 相比,B+Tree 有以下不同点:
|
||||
|
@ -325,7 +325,7 @@ InnoDB 的 B+Tree 索引分为主索引和辅助索引。
|
|||
###### 顺序访问指针的 B+Tree
|
||||
|
||||
<div align="center">
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-d97c1144093e2841.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"/>
|
||||
<img src="http://upload-images.jianshu.io/upload_images/3101171-d97c1144093e2841.png"/>
|
||||
</div>
|
||||
|
||||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 基础上进行了优化,在叶子节点增加了顺序访问指针,做这个优化的目的是为了提高区间访问的性能。
|
||||
|
@ -531,7 +531,7 @@ Mysql 支持两种复制:基于行的复制和基于语句的复制。
|
|||
- **SQL 线程** :负责读取中继日志并重放其中的 SQL 语句。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/master-slave.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/mysql/master-slave.png!zp" />
|
||||
</div>
|
||||
|
||||
### 7.2. 读写分离
|
||||
|
@ -547,7 +547,7 @@ MySQL 读写分离能提高性能的原因在于:
|
|||
- 增加冗余,提高可用性。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/master-slave-proxy.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/mysql/master-slave-proxy.png!zp" />
|
||||
</div>
|
||||
|
||||
## 8. 参考资料
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
>
|
||||
> 关键词:Database, RDBM, psql
|
||||
|
||||
<br><div align="center"><img src="https://raw.githubusercontent.com/dunwu/images/master/snap/20180920181010182614.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/snap/20180920181010182614.png!zp"/></div><br>
|
||||
|
||||
<!-- TOC depthFrom:2 depthTo:3 -->
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
|
||||
官方下载页面要求用户选择相应版本,然后动态的给出安装提示,如下图所示:
|
||||
|
||||
<br><div align="center"><img src="https://raw.githubusercontent.com/dunwu/images/master/snap/20180920181010174348.png"/></div><br>
|
||||
<br><div align="center"><img src="http://dunwu.test.upcdn.net/snap/20180920181010174348.png!zp"/></div><br>
|
||||
|
||||
前 3 步要求用户选择,后 4 步是根据选择动态提示的安装步骤
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
### 2.1. SQL 语法结构
|
||||
|
||||
<p align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/sql-syntax.png" alt="sql-syntax">
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/mysql/sql-syntax.png!zp" alt="sql-syntax">
|
||||
</p>
|
||||
|
||||
SQL 语法结构包括:
|
||||
|
@ -538,7 +538,7 @@ HAVING COUNT(*) >= 1;
|
|||
- 子查询必须被圆括号 `()` 括起来。
|
||||
- 内部查询首先在其父查询之前执行,以便可以将内部查询的结果传递给外部查询。执行过程可以参考下图:
|
||||
<p align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/sql-subqueries.gif" alt="sql-subqueries">
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/mysql/sql-subqueries.gif!zp" alt="sql-subqueries">
|
||||
</p>
|
||||
|
||||
**子查询的子查询**
|
||||
|
@ -573,7 +573,7 @@ WHERE cust_id IN (SELECT cust_id
|
|||
> - 连接可以替换子查询,并且比子查询的效率一般会更快。
|
||||
>
|
||||
> <div align="center">
|
||||
> <img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/sql-join.png" alt="sql-join">
|
||||
> <img src="http://dunwu.test.upcdn.net/images/database/mysql/sql-join.png!zp" alt="sql-join">
|
||||
> </div>
|
||||
|
||||
#### 1.8.1.1. 内连接(INNER JOIN)
|
||||
|
|
|
@ -62,7 +62,7 @@ CALL phelloword()
|
|||
|
||||
我们应该做到:**他们想看到什么样的数据,我们就给他们什么样的数据...一方面就能够让他们只关注自己的数据,另一方面,我们也保证数据表一些保密的数据不会泄露出来...**
|
||||
|
||||
![img](https://user-gold-cdn.xitu.io/2018/3/5/161f3de9b3092439?imageView2/0/w/1280/h/960/format/webp/ignore-error/1)
|
||||
<div align="center"><img src="https://user-gold-cdn.xitu.io/2018/3/5/161f3de9b3092439?imageView2/0/w/1280/h/960/format/webp/ignore-error/1"/></div>
|
||||
|
||||
我们在查询数据的时候,常常需要编写非常长的 SQL 语句,几乎每次都要写很长很长....上面已经说了,**视图就是基于查询的一种虚表,也就是说,视图可以将查询出来的数据进行封装。。。那么我们在使用的时候就会变得非常方便**...
|
||||
|
||||
|
@ -134,7 +134,7 @@ CALL phelloword()
|
|||
对于任意结点,其内部的关键字 Key 是升序排列的。每个节点中都包含了 data。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/B-TREE.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/B-TREE.png!zp" />
|
||||
</div>
|
||||
|
||||
对于每个结点,主要包含一个关键字数组 Key[],一个指针数组(指向儿子)Son[]。
|
||||
|
@ -153,7 +153,7 @@ B+Tree 是 B-Tree 的变种:
|
|||
- 非叶子节点不存储 data,只存储 key;叶子节点不存储指针。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/B+TREE.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/B+TREE.png!zp" />
|
||||
</div>
|
||||
|
||||
由于并不是所有节点都具有相同的域,因此 B+Tree 中叶节点和内节点一般大小不同。这点与 B-Tree 不同,虽然 B-Tree 中不同节点存放的 key 和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中 B-Tree 往往对每个节点申请同等大小的空间。
|
||||
|
@ -163,7 +163,7 @@ B+Tree 是 B-Tree 的变种:
|
|||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 的基础上进行了优化,增加了顺序访问指针。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/带有顺序访问指针的B+Tree.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/带有顺序访问指针的B+Tree.png!zp" />
|
||||
</div>
|
||||
|
||||
在 B+Tree 的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的 B+Tree。
|
||||
|
@ -449,11 +449,11 @@ mycat 这种 proxy 层方案的**缺点在于需要部署**,自己运维一套
|
|||
|
||||
**水平拆分**的意思,就是把一个表的数据给弄到多个库的多个表里去,但是每个库的表结构都一样,只不过每个库表放的数据是不同的,所有库表的数据加起来就是全部数据。水平拆分的意义,就是将数据均匀放更多的库里,然后用多个库来扛更高的并发,还有就是用多个库的存储容量来进行扩容。
|
||||
|
||||
[![database-split-horizon](https://github.com/doocs/advanced-java/raw/master/images/database-split-horizon.png)](https://github.com/doocs/advanced-java/blob/master/images/database-split-horizon.png)
|
||||
<div align="center"><img src="https://github.com/doocs/advanced-java/blob/master/images/database-split-horizon.png"/></div>
|
||||
|
||||
**垂直拆分**的意思,就是**把一个有很多字段的表给拆分成多个表**,**或者是多个库上去**。每个库表的结构都不一样,每个库表都包含部分字段。一般来说,会**将较少的访问频率很高的字段放到一个表里去**,然后**将较多的访问频率很低的字段放到另外一个表里去**。因为数据库是有缓存的,你访问频率高的行字段越少,就可以在缓存里缓存更多的行,性能就越好。这个一般在表层面做的较多一些。
|
||||
|
||||
[![database-split-vertically](https://github.com/doocs/advanced-java/raw/master/images/database-split-vertically.png)](https://github.com/doocs/advanced-java/blob/master/images/database-split-vertically.png)
|
||||
<div align="center"><img src="https://github.com/doocs/advanced-java/blob/master/images/database-split-vertically.png"/></div>
|
||||
|
||||
这个其实挺常见的,不一定我说,大家很多同学可能自己都做过,把一个大表拆开,订单表、订单支付表、订单商品表。
|
||||
|
||||
|
@ -558,7 +558,7 @@ MySQL 读写分离能提高性能的原因在于:
|
|||
- 增加冗余,提高可用性。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/mysql/master-slave-proxy.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/mysql/master-slave-proxy.png!zp" />
|
||||
</div>
|
||||
|
||||
#### 1.7.1.2. 垂直切分
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
> 事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库事务.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库事务.png!zp"/>
|
||||
</div>
|
||||
### 1.1. ACID
|
||||
|
||||
|
@ -72,7 +72,7 @@
|
|||
> - 事务满足持久化是为了能应对数据库奔溃的情况。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库ACID.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库ACID.png!zp"/>
|
||||
</div>
|
||||
|
||||
### 1.2. 并发一致性问题
|
||||
|
@ -84,28 +84,28 @@
|
|||
T<sub>1</sub> 和 T<sub>2</sub> 两个事务都对一个数据进行修改,T<sub>1</sub> 先修改,T<sub>2</sub> 随后修改,T<sub>2</sub> 的修改覆盖了 T<sub>1</sub> 的修改。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库并发一致性-丢失修改.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库并发一致性-丢失修改.png!zp"/>
|
||||
</div>
|
||||
- **脏数据**
|
||||
|
||||
T<sub>1</sub> 修改一个数据,T<sub>2</sub> 随后读取这个数据。如果 T<sub>1</sub> 撤销了这次修改,那么 T<sub>2</sub> 读取的数据是脏数据。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库并发一致性-脏数据.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库并发一致性-脏数据.png!zp"/>
|
||||
</div>
|
||||
- **不可重复读**
|
||||
|
||||
T<sub>2</sub> 读取一个数据,T<sub>1</sub> 对该数据做了修改。如果 T<sub>2</sub> 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库并发一致性-不可重复读.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库并发一致性-不可重复读.png!zp"/>
|
||||
</div>
|
||||
- **幻读**
|
||||
|
||||
T<sub>1</sub> 读取某个范围的数据,T<sub>2</sub> 在这个范围内插入新的数据,T<sub>1</sub> 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库并发一致性-幻读.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库并发一致性-幻读.png!zp"/>
|
||||
</div>
|
||||
并发一致性解决方案:
|
||||
|
||||
|
@ -326,7 +326,7 @@ MVCC 使用到的快照存储在 Undo 日志中,该日志通过回滚指针把
|
|||
将当前系统版本号作为数据行快照的创建版本号。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/mvcc_insert.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/mvcc_insert.png!zp"/>
|
||||
</div>
|
||||
|
||||
#### DELETE
|
||||
|
@ -334,7 +334,7 @@ MVCC 使用到的快照存储在 Undo 日志中,该日志通过回滚指针把
|
|||
将当前系统版本号作为数据行快照的删除版本号。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/mvcc_delete.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/mvcc_delete.png!zp"/>
|
||||
</div>
|
||||
|
||||
#### UPDATE
|
||||
|
@ -342,7 +342,7 @@ MVCC 使用到的快照存储在 Undo 日志中,该日志通过回滚指针把
|
|||
将当前系统版本号作为更新后的数据行快照的创建版本号,同时将当前系统版本号作为更新前的数据行快照的删除版本号。可以理解为先执行 DELETE 后执行 INSERT。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/mvcc_update.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/mvcc_update.png!zp"/>
|
||||
</div>
|
||||
|
||||
### 3.4. 快照读与当前读
|
||||
|
@ -481,7 +481,7 @@ B-Tree 不同于 Binary Tree(二叉树,最多有两个子树),它是平
|
|||
对于任意结点,其内部的关键字 Key 是升序排列的。每个节点中都包含了 data。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/B-TREE.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/B-TREE.png!zp" />
|
||||
</div>
|
||||
|
||||
对于每个结点,主要包含一个关键字数组 Key[],一个指针数组(指向儿子)Son[]。
|
||||
|
@ -500,7 +500,7 @@ B+Tree 是 B-Tree 的变种:
|
|||
- 非叶子节点不存储 data,只存储 key;叶子节点不存储指针。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/B+TREE.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/B+TREE.png!zp" />
|
||||
</div>
|
||||
|
||||
由于并不是所有节点都具有相同的域,因此 B+Tree 中叶节点和内节点一般大小不同。这点与 B-Tree 不同,虽然 B-Tree 中不同节点存放的 key 和指针可能数量不一致,但是每个节点的域和上限是一致的,所以在实现中 B-Tree 往往对每个节点申请同等大小的空间。
|
||||
|
@ -510,7 +510,7 @@ B+Tree 是 B-Tree 的变种:
|
|||
一般在数据库系统或文件系统中使用的 B+Tree 结构都在经典 B+Tree 的基础上进行了优化,增加了顺序访问指针。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/带有顺序访问指针的B+Tree.png" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/带有顺序访问指针的B+Tree.png!zp" />
|
||||
</div>
|
||||
|
||||
在 B+Tree 的每个叶子节点增加一个指向相邻叶子节点的指针,就形成了带有顺序访问指针的 B+Tree。
|
||||
|
@ -607,7 +607,7 @@ SELECT ... WHERE TO_DAYS(CURRENT_DAT) - TO_DAYS(date_col) <= 10;
|
|||
### 6.1. 水平拆分
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库水平拆分.jpg" width="500" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库水平拆分.jpg!zp" width="500" />
|
||||
</div>
|
||||
|
||||
对于海量数据的数据库,如果表并不多,但每张表的数据非常多,这时候适合水平切分,即把表的数据按某种规则(比如按 ID 散列)切分到多个数据库(server)上。
|
||||
|
@ -617,7 +617,7 @@ SELECT ... WHERE TO_DAYS(CURRENT_DAT) - TO_DAYS(date_col) <= 10;
|
|||
### 6.2. 垂直拆分
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库垂直拆分.jpg" width="500" />
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库垂直拆分.jpg!zp" width="500" />
|
||||
</div>
|
||||
|
||||
垂直切分是将一张表按列切分成多个表,通常是按照列的关系密集程度进行切分,也可以利用垂直切分将经常被使用的列和不经常被使用的列切分到不同的表中。
|
||||
|
@ -734,7 +734,7 @@ SELECT ... WHERE TO_DAYS(CURRENT_DAT) - TO_DAYS(date_col) <= 10;
|
|||
高级别范式的依赖于低级别的范式,1NF 是最低级别的范式。
|
||||
|
||||
<div align="center">
|
||||
<img src="https://gitee.com/turnon/images/raw/master/images/database/RDB/数据库范式.png"/>
|
||||
<img src="http://dunwu.test.upcdn.net/images/database/RDB/数据库范式.png!zp"/>
|
||||
</div>
|
||||
|
||||
#### 第一范式 (1NF)
|
||||
|
|
Loading…
Reference in New Issue