Skip to content

Commit 6877d82

Browse files
author
JasonLou
committed
更新 数据库
1 parent 13d153e commit 6877d82

33 files changed

Lines changed: 1428 additions & 163 deletions

‎Java应届生面试突击/数据库/01_数据库专题.md‎

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,66 +17,69 @@ by 涉及的列上建立索引。
1717

1818
#### 2.优化 SQL 语句
1919
    
20-
2.1 通过 explain(查询优化神器)用来查看 SQL 语句的执行效果,
20+
2.1 通过 explain(查询优化神器)用来查看 SQL 语句的执行效果,
2121
可以帮助选择更好的索引和优化查询语句, 写出更好的优化语句。 通
2222
常我们可以对比较复杂的尤其是涉及到多表的 SELECT 语句, 把关
2323
键字 EXPLAIN 加到前面, 查看执行计划。例如: explain select * from
2424
news; <br>
2525
&ensp;&ensp;&ensp;&ensp;
26-
2.2 任何地方都不要使用 select * from t , 用具体的字段列表代
26+
2.2 任何地方都不要使用 select * from t , 用具体的字段列表代
2727
替“*” , 不要返回用不到的任何字段。 <br>
2828
&ensp;&ensp;&ensp;&ensp;
29-
2.3 不在索引列做运算或者使用函数。 <br>
29+
2.3 不在索引列做运算或者使用函数。 <br>
3030
&ensp;&ensp;&ensp;&ensp;
31-
2.4 查询尽可能使用 limit 减少返回的行数, 减少数据传输时间和
31+
2.4 查询尽可能使用 limit 减少返回的行数, 减少数据传输时间和
3232
带宽浪费。
3333

3434
#### 3.优化数据库对象
3535
3.1 优化表的数据类型 <br>
3636
&ensp;&ensp;&ensp;&ensp;
37-
使用 procedure analyse()函数对表进行分析, 该函数可以对表
37+
使用 procedure analyse()函数对表进行分析, 该函数可以对表
3838
中列的数据类型提出优化建议。 能小就用小。 表数据类型第一个原
3939
则是: 使用能正确的表示和存储数据的最短类型。 这样可以减少对
4040
磁盘空间、 内存、 cpu 缓存的使用。
4141
使用方法: select * from 表名 procedure analyse(); <br>
4242
3.2 对表进行拆分 <br>
4343
&ensp;&ensp;&ensp;&ensp;
44-
通过拆分表可以提高表的访问效率。 有 2 种拆分方法: <br>
44+
通过拆分表可以提高表的访问效率。 有 2 种拆分方法: <br>
4545
&ensp;&ensp;&ensp;&ensp;
46-
1.垂直拆分:
47-
把主键和一些列放在一个表中, 然后把主键和另外的列放在另
46+
1.垂直拆分: <br>
47+
&ensp;&ensp;&ensp;&ensp;
48+
把主键和一些列放在一个表中, 然后把主键和另外的列放在另
4849
一个表中。 如果一个表中某些列常用, 而另外一些不常用, 则可以
4950
采用垂直拆分。 <br>
5051
&ensp;&ensp;&ensp;&ensp;
51-
2.水平拆分:
52-
根据一列或者多列数据的值把数据行放到二个独立的表中。 <br>
52+
2.水平拆分: <br>
53+
&ensp;&ensp;&ensp;&ensp;
54+
根据一列或者多列数据的值把数据行放到二个独立的表中。 <br>
5355
3.3 使用中间表来提高查询速度 <br>
5456
&ensp;&ensp;&ensp;&ensp;
55-
创建中间表, 表结构和源表结构完全相同, 转移要统计的数据
57+
创建中间表, 表结构和源表结构完全相同, 转移要统计的数据
5658
到中间表, 然后在中间表上进行统计, 得出想要的结果。
5759

5860
#### 4.硬件优化 <br>
5961
4.1 CPU 的优化 <br>
6062
&ensp;&ensp;&ensp;&ensp;
61-
选择多核和主频高的 CPU。 <br>
63+
选择多核和主频高的 CPU。 <br>
6264
4.2 内存的优化 <br>
6365
&ensp;&ensp;&ensp;&ensp;
64-
使用更大的内存。 将尽量多的内存分配给 MYSQL 做缓存。 <br>
66+
使用更大的内存。 将尽量多的内存分配给 MYSQL 做缓存。 <br>
6567
4.3 磁盘 I/O 的优化 <br>
6668

6769
4.3.1 使用磁盘阵列 <br>
6870
&ensp;&ensp;&ensp;&ensp;
69-
RAID 0 没有数据冗余, 没有数据校验的磁盘陈列。 实现 RAID 0
71+
RAID 0 没有数据冗余, 没有数据校验的磁盘陈列。 实现 RAID 0
7072
至少需要两块以上的硬盘, 它将两块以上的硬盘合并成一块, 数据
7173
连续地分割在每块盘上。 <br>
7274
&ensp;&ensp;&ensp;&ensp;
73-
RAID1 是将一个两块硬盘所构成 RAID 磁盘阵列, 其容量仅等于
75+
RAID1 是将一个两块硬盘所构成 RAID 磁盘阵列, 其容量仅等于
7476
一块硬盘的容量, 因为另一块只是当作数据“镜像”。
75-
使用 RAID-0+1 磁盘阵列。 RAID 0+1 是 RAID 0 和 RAID 1 的组
77+
&ensp;&ensp;&ensp;&ensp;
78+
使用 RAID-0+1 磁盘阵列。 RAID 0+1 是 RAID 0 和 RAID 1 的组
7679
合形式。 它在提供与 RAID 1 一样的数据安全保障的同时, 也提供了
7780
与 RAID 0 近似的存储性能。 <br>
78-
图
79-
81+
![01_1_1](/data/images/Java应届生面试突击/数据库/01_1_1.png) <br>
82+
8083
4.3.2 调整磁盘调度算法 <br>
8184
&ensp;&ensp;&ensp;&ensp;
8285
选择合适的磁盘调度算法, 可以减少磁盘的寻道时间。
@@ -104,19 +107,19 @@ RAID1 是将一个两块硬盘所构成 RAID 磁盘阵列, 其容量仅等于
104107
&ensp;&ensp;&ensp;&ensp;
105108
目前,大部分的主流关系型数据库都提供了主从复制的功能,通过配置两台(或多台)
106109
数据库的主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。网站可
107-
以利用数据库的这一功能,实现数据库的读写分离,从而改善数据库的负载压力。一个系
110+
以利用数据库的这一功能,*实现数据库的读写分离,从而改善数据库的负载压力*。一个系
108111
统的读操作远远多于写操作,因此写操作发向 master,读操作发向 slaves 进行操作(简
109112
单的轮循算法来决定使用哪个 slave)。 <br>
110113
&ensp;&ensp;&ensp;&ensp;
111114
利用数据库的读写分离,Web 服务器在写数据的时候,访问主数据库(Master),主
112-
数据库通过主从复制机制将数据更新同步到从数据库(Slave),这样当 Web 服务器读数
115+
数据库通过*主从复制机制*将数据更新同步到从数据库(Slave),这样当 Web 服务器读数
113116
据的时候,就可以通过从数据库获得数据。这一方案使得在大量读操作的 Web 应用可以轻
114117
松地读取数据,而主数据库也只会承受少量的写入操作,还可以实现数据热备份,可谓是
115118
一举两得的方案。 <br>
119+
![01_1_2](/data/images/Java应届生面试突击/数据库/01_1_2.png) <br>
116120

117-
图
118121

119-
主从复制的原理: <br>
122+
##### 主从复制的原理: <br>
120123
&ensp;&ensp;&ensp;&ensp;
121124
影响 MySQL-A 数据库的操作,在数据库执行后,都会写入本地的日志系统 A 中。
122125
假设,实时的将变化了的日志系统中的数据库事件操作,通过网络发给 MYSQL-B。
@@ -135,54 +138,55 @@ slave。 <br>
135138
可以发现,通过上面的机制,可以保证 MYSQL-A 和 MYSQL-B 的数据库数据一致,但
136139
是时间上肯定有延迟,即 MYSQL-B 的数据是滞后的。 <br>
137140

138-
简化版: <br>
141+
##### 简化版: <br>
139142
mysql 主(称 master)从(称 slave)复制的原理: <br>
140143
&ensp;&ensp;&ensp;&ensp;
141-
(1)master 将数据改变记录到二进制日志(binary log)中,也即是配置文件 log-bin 指定
144+
(1)master 将数据改变记录到二进制日志(binary log)中,也即是配置文件 log-bin 指定
142145
的文件(这些记录叫做二进制日志事件, binary log events) <br>
143-
PS:从图中可以看出,Slave 服务器中有一个 I/O线程(I/O Thread)在不停地监听 Master
146+
*PS*:从图中可以看出,Slave 服务器中有一个 I/O线程(I/O Thread)在不停地监听 Master
144147
的二进制日志(Binary Log)是否有更新: 如果没有它会睡眠等待 Master 产生新的日志事件;
145148
如果有新的日志事件(Log Events), 则会将其拷贝至 Slave 服务器中的中继日志(Relay
146149
Log)。 <br>
147150
&ensp;&ensp;&ensp;&ensp;
148-
(2).slave 将 master 的二进制日志事件(binary log events)拷贝到它的中继日志(relay
151+
(2).slave 将 master 的二进制日志事件(binary log events)拷贝到它的中继日志(relay
149152
log) <br>
150153
&ensp;&ensp;&ensp;&ensp;
151-
(3).slave 重做中继日志中的事件,将 Master 上的改变反映到它自己的数据库中。所
154+
(3).slave 重做中继日志中的事件,将 Master 上的改变反映到它自己的数据库中。所
152155
以两端的数据是完全一样的。 <br>
153-
154-
PS: 从图中可以看出, Slave 服务器中有一个 SQL 线程(SQL Thread)从中继日志读
156+
&ensp;&ensp;&ensp;&ensp;
157+
*PS*: 从图中可以看出, Slave 服务器中有一个 SQL 线程(SQL Thread)从中继日志读
155158
取事件, 并重做其中的事件, 从而更新 Slave 的数据, 使其与 Master 中的数据一致。 只要
156159
该线程与 I/O 线程保持一致,中继日志通常会位于 OS 的缓存中,所以中继日志的开销很小。
157160
附简要原理图:
158-
图
161+
![01_1_3](/data/images/Java应届生面试突击/数据库/01_1_3.png) <br>
162+
159163

160-
主从复制的几种方式: <br>
161-
1.同步复制 <br>
164+
##### 主从复制的几种方式: <br>
165+
1. 同步复制 <br>
162166
&ensp;&ensp;&ensp;&ensp;
163-
主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,必须等待验证所
164-
有的从服务器的更新数据是否已经复制到其中,之后才可以自由处理其它进入的事务处理
167+
主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,必须等待验证*所
168+
有的从服务器*的更新数据是否已经复制到其中,之后才可以自由处理其它进入的事务处理
165169
请求。
166-
2.异步复制 <br>
170+
2. 异步复制 <br>
167171
&ensp;&ensp;&ensp;&ensp;
168172
主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,无需等待验证更
169173
新数据是否已经复制到从服务器中,就可以自由处理其它进入的事务处理请求。
170-
3.半同步复制 <br>
174+
3. 半同步复制 <br>
171175
&ensp;&ensp;&ensp;&ensp;
172-
主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,只需等待验证其
173-
中一台从服务器的更新数据是否已经复制到其中,就可以自由处理其它进入的事务处理请
176+
主服务器在将更新的数据写入它的二进制日志(Binlog)文件中后,只需等待验证*其
177+
中一台从服务器*的更新数据是否已经复制到其中,就可以自由处理其它进入的事务处理请
174178
求,其他的从服务器不用管。 <br>
175179

176180
### <a name="3">3. 数据库分表, 分区, 分库</a>
177181
&ensp;&ensp;&ensp;&ensp;
178-
分表见上面描述。 <br>
182+
*分表*见上面描述。 <br>
179183
&ensp;&ensp;&ensp;&ensp;
180-
分区就是把一张表的数据分成多个区块,这些区块可以在一个磁盘上,也可以在不同
184+
*分区*就是把一张表的数据分成多个区块,这些区块可以在一个磁盘上,也可以在不同
181185
的磁盘上,分区后,表面上还是一张表,但数据散列在多个位置,这样一来,多块硬盘同
182186
时处理不同的请求,从而提高磁盘 I/O 读写性能,实现比较简单。 包括水平分区和垂直分
183187
区。 <br>
184188
&ensp;&ensp;&ensp;&ensp;
185-
分库是根据业务不同把相关的表切分到不同的数据库中,比如 web、bbs、blog 等库。 <br>
189+
*分库*是根据业务不同把相关的表切分到不同的数据库中,比如 web、bbs、blog 等库。 <br>
186190

187191
---
188192
### 搬运工信息

‎Java应届生面试突击/数据库/02_sql注入的问题.md‎

Lines changed: 51 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,82 +8,86 @@
88

99

1010
### <a name="1">1. SQL 语句应该考虑哪些安全问题?</a>
11-
1.防止 sql 注入, 对特殊字符进行过滤、 转义或者使用预编译的 sql 语句绑定变量。 <br>
12-
2.当 sql 语句运行出错时, 不要把数据库返回的错误信息全部显示给用户, 以防止
13-
泄漏服务器和数据库相关信息。 <br>
11+
&ensp;&ensp;&ensp;&ensp;
12+
1.防止 sql 注入, 对特殊字符进行过滤、 转义或者使用预编译的 sql 语句绑定变量。 <br>
13+
&ensp;&ensp;&ensp;&ensp;
14+
2.当 sql 语句运行出错时, *不要把数据库返回的错误信息*全部显示给用户, 以*防止
15+
泄漏*服务器和数据库相关信息。 <br>
1416

1517
### <a name="2">2. 什么叫SQL注入,如何防止?请举例说明。</a>
1618
举个例子: <br>
1719
&ensp;&ensp;&ensp;&ensp;
18-
你后台写的 java 代码拼的 sql 如下:
19-
20-
// 该 ename 为前台传过来的一个查询条件
20+
你后台写的 java 代码拼的 sql 如下:
21+
```java
22+
// 该 ename 为前台传过来的一个查询条件
2123
public List getInfo(String ename){
22-
StringBuffer buf = new StringBuffer();
23-
buf.append("select empno,ename,deptno from emp where ename =
24-
'").append(ename).append("'");
25-
...
26-
...
27-
...
24+
StringBuffer buf = new StringBuffer();
25+
buf.append("select empno,ename,deptno from emp where ename = '").append(ename).append("'");
26+
...
27+
...
28+
...
2829
}
29-
30+
```
31+
3032
而前台页面有个输入框如下: <br>
3133
职员姓名: __________ <br>
3234
该文本域对应上面方法的 ename 参数。 <br>
3335
如果用户在查询时向职员姓名文本域中输入的是如下信息: <br>
34-
35-
' or '1'='1
36-
36+
```sql
37+
' or '1'='1
38+
```
3739
那么这时就会涉及到 sql 注入这个概念了。 <br>
38-
上面的字符串传到后台后, 与其它 select 等字符串拼成了如下的语句: <br>
39-
40-
select empno,ename,deptno from emp where ename = '' or '1'='1'
41-
42-
上面的 where 条件是永远成立的, 如果你的表中有权限限制, 比如只能查询本地市的信息,
40+
*上面的字符串传到后台后, 与其它 select 等字符串拼成了如下的语句*: <br>
41+
```sql
42+
select empno,ename,deptno from emp where ename = '' or '1'='1'
43+
```
44+
*上面的 where 条件是永远成立的*, 如果你的表中有权限限制, 比如只能查询本地市的信息,
4345
过滤条件中有地市过滤, 不过因为输入 ' or '1'='1 字符串后, 条件永远成立, 导致你能看到
4446
所有城市的职员信息, 那就会产生权限问题了, 用户能看到不该看到的信息。 同理, 如果
4547
是 insert 或者 update 等语句的话, 通过 sql 注入会产生不可估量的问题。 <br>
4648
&ensp;&ensp;&ensp;&ensp;
47-
这种不安全的情况是在 SQL 语句在拼接的情况下发生。 <br>
49+
这种不安全的情况是在 SQL 语句*在拼接的情况下*发生。 <br>
4850
&ensp;&ensp;&ensp;&ensp;
49-
解决方法: <br>
50-
1.参数绑定 <br>
51+
52+
#### 解决方法:
53+
1. 参数绑定 <br>
5154
&ensp;&ensp;&ensp;&ensp;
5255
为了防范这样” SQL 注入安全“可以用预编译解决(不要用拼
5356
接 SQL 字符串,可以用 prepareStatement,参数用 set 方法进行填装 ) 。 <br>
57+
```java
58+
String sql= "insert into userlogin values(?,?)";
59+
try {
60+
PreparedStatement ps=conn.prepareStatement(sql);
61+
for(int i=1;i<100;i++){
62+
ps.setInt(1, i);
63+
ps.setInt(2, 8888);
64+
ps.executeUpdate();
65+
}
66+
ps.close();
67+
conn.close();
68+
} catch (SQLException e) {
69+
e.printStackTrace();
70+
}
71+
```
5472

55-
String sql= "insert into userlogin values(?,?)";
56-
try {
57-
PreparedStatement ps=conn.prepareStatement(sql);
58-
for(int i=1;i<100;i++){
59-
ps.setInt(1, i);
60-
ps.setInt(2, 8888);
61-
ps.executeUpdate();
62-
}
63-
ps.close();
64-
conn.close();
65-
} catch (SQLException e) {
66-
e.printStackTrace();
67-
}
68-
69-
2.检查变量的数据类型和格式 <br>
73+
2. 检查变量的数据类型和格式 <br>
7074
&ensp;&ensp;&ensp;&ensp;
71-
如果你的 SQL 语句是类似 where id={$id}这种形式, 数据库里所有的 id 都是
72-
数字, 那么就应该在 SQL 被执行前, 检查确保变量 id 是 int 类型; 如果是接受
75+
如果你的 SQL 语句是类似 where id={$id}这种形式, *数据库里所有的 id 都是
76+
数字, 那么就应该在 SQL 被执行前, 检查确保变量 id 是 int 类型*; 如果是接受
7377
邮箱, 那就应该检查并严格确保变量一定是邮箱的格式, 其他的类型比如日期、
74-
时间等也是一个道理。 总结起来: 只要是有固定格式的变量, 在 SQL 语句执行
78+
时间等也是一个道理。 总结起来: *只要是有固定格式的变量, 在 SQL 语句执行
7579
前, 应该严格按照固定格式去检查, 确保变量是我们预想的格式, 这样很大程
76-
度上可以避免 SQL 注入攻击。 <br>
80+
度上可以避免 SQL 注入攻击。* <br>
7781
&ensp;&ensp;&ensp;&ensp;
7882
比如, 我们前面接受 username 参数例子中, 我们的产品设计应该是在用户
79-
注册的一开始, 就有一个用户名的命名规则, 比如 5-20 个字符, 只能由大小写
83+
注册的一开始, *就有一个用户名的命名规则*, 比如 5-20 个字符, 只能由大小写
8084
字母、 数字以及一些安全的符号组成, 不包含特殊字符。 此时我们应该有一个
8185
check_username 的函数来进行统一的检查。 不过, 仍然有很多例外情况并不能
8286
应用到这一准则, 比如文章发布系统, 评论系统等必须要允许用户提交任意字
83-
符串的场景, 这就需要采用过滤等其他方案了。 (使用正则表达式进行格式验
84-
证! ) <br>
87+
符串的场景, 这就需要采用过滤等其他方案了。 (*使用正则表达式进行格式验
88+
证!*) <br>
8589

86-
3.所有的 SQL 语句都封装在存储过程中。 <br>
90+
3. 所有的 SQL 语句都封装在*存储过程*中。 <br>
8791
&ensp;&ensp;&ensp;&ensp;
8892
所有的 SQL 语句都封装在存储过程中, 这样不但可以避免 SQL 注入, 还能
8993
提高一些性能。

0 commit comments

Comments
 (0)