发表于: 2020-04-29 23:07:15
1 1268
今天完成的事情:
看了spring 事务管理
主要分为5个部分
1. 事物传播行为介绍:
Propagation.REQUIRED :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
Propagation.NOT_SUPPORTED) :容器不为这个方法开启事务
Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常
Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
概念很官方,昨天看这个给我看的头疼
自己整理后后面才慢慢理解
比如在A方法包含B方法时
methodA(){
//代码块
methodB(){
//代码块
}
}
只设置方法A事务传播行为 决定B是否跟A一起运行 ,或者B能否单独运行事务
或同时设置A B的事务传播行为, 决定A和B的事务执行逻辑,是绑定在一起执行事务还是互相隔离执行事务。
2.隔离级别
这个跟数据库的一样 , 定义了一个事务可能受其他并发事务影响的程度。
目的是为了防止脏读,幻读,不可重复读等问题(不举例了)
Isolation.DEFAULT:采用后端数据库的默认的隔离级别
Isolation.READ_UNCOMMITTED:读取未提交数据(会出现脏读, 不可重复读) 基本不使用
Isolation.READ_COMMITTED:读取已提交数据(会出现不可重复读和幻读)
Isolation.REPEATABLE_READ:可重复读(会出现幻读)
Isolation.SERIALIZABLE: 最高最安全的级别,以上问题都可以防止,但运行慢。
3.只读
事务的第三个特性是它是否为只读事务。如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来进行一些特定的优化。通过将事务设置为只读,你就可以给数据库一个机会,让它应用它认为合适的优化措施。
4.事务超时
为了使应用程序很好地运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源。事务超时就是事务的一个定时器,在特定时间内事务如果没有执行完毕,那么就会自动回滚,而不是一直等待其结束。
5.回滚规则
回滚规则定义了哪些异常会导致事务回滚而哪些不会。
默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚
但是你可以声明事务在遇到特定的检查型异常时像遇到运行期异常那样回滚。同样,你还可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。
一个配置事务属性的例子:
@Transactional(propagation=Propagation.REQUIRES_NEW, (1)
isolation=Isolation.READ_COMMITTED, (2)
noRollbackFor={Exception.class}, (3)
(4)readOnly=true, (5) timeout=3)
public void A(){
B();
C();
}
(1)REQUIRES_NEW:相互独立 B事务提交 A不能对其进行回滚。
(2)使用isolation 指定事务的隔离级别,最常用的取值为READ_COMMITTED,读取已提交数据(会出现不可重复读和幻读)
(3)默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置。通常情况下,默认值即可。
(4)使用readOnly 指定事务是否为只读。 表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务。
(5)使用timeOut 指定强制回滚之前事务可以占用的时间,这里3是3分钟。
继续进行深度思考:
3.在端到端的请求当中,建立Http连接需要多久,Model通过JSP转成Json需要多久,Nginx调用Resin需要多久,Service访问DB需要多久,一个Sql语句执行的时间是多久。
网络请求的损耗过程:
第一部分前端的响应,一般包括解析和渲染,这部分的性能跟前端的代码,前端硬件有关系。
客户端到服务器端的响应时间,可以通过浏览器的F12来查看
第二部分就是网络延迟,这部分的代码正常来讲是在8~16MS左右,是的,Http请求就是差不多这个性能,如果是WebSocket几乎可以做到零延迟。
第三部分就是服务器端的响应,我们说的是网站慢,一般而言,也就是主要在这里,要做性能优化的地方,基本上也是看这里。
nginx配置日志 一个请求只用了大概 0.002ms
tomca配置日志 一个完整请求平均在20 -40ms
其他时间需要配置AOP 在代码里输出controller层内
调用service接口的完成时间(service访问DB)
调用dao接口的完成时间(sql语句执行)
4.什么是Sql注入,应该怎么解决?对于未做SQL注入防范的程序,你可以直接通过调用接口删掉表吗?
SQL注入是一种注入攻击,可以执行恶意SQL语句。
而SQL注入是将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令。
获取关键数据,或者对我们的数据库进行破坏。
如何防止sql注入:
1. 可以使用PreparedStatement ,它把用户非法输入的单引号用\反斜杠做转义,从而达到了防止sql注入的目的
2.使用正则表达式过滤传入的参数
3.对普通用户和管理员权限进行严格区分。
4.检测输入的参数中是否包含非法字符。
可以 假如一个数据库登陆页面要输入账号密码
可以在bb后面添加 ; DROP TABLE userLogin ;
SELECT * FROM userLogin WHERE username= 'aa',password='bb';DROP TABLE userLogin ;
即可删除数据表(需要知道数据表名称)
5.在内存里拼装数据会节省时间吗?如果不能,为什么要选择单表查询,而不是直接拼装成Sql语句。
拼装sql语句查询容易造成sql语句疏忽,给有目的这造成sql注入来攻击,篡改数据库
6.为什么一般而言,不允许使用连表查询,不允许使用复杂的Group By等语句,为什么不允许使用存储过程?
使用联表查询和存储过程在一定程度上会占用数据库的性能,消耗更多的内存资源,把这些逻辑放在Java代码中处理可以节省数据库的性能。
还能降低了业务之间的耦合,增加了扩展性。
group by 的缺点 当group设计到子查询时 比如
select * from (select * from table where xx=xx ) as A group by xx
1.除了算法使用的字段和group by 以外的字段,其它字段的值是随机的,默认获取的是选择查询索引(where或者group by)的第一条符合分组的记录填充的。
2、当子查询的结果非常大的时候,数据库服务器的临时表空间会用完,因此多余的查询数据会丢失
3、子查询生成的临时表,没有索引可用,如果临时表数据很大,则主select语句的效率也很低
7.为什么响应时间一般不允许超过200MS,怎么查看一个请求从发起到结束,耗费在什么地方了?
人的眼睛对200MS以上的延迟是有反应的,所以最好一整个页面都应该在200MS之内完成;
可以通过aop来记录service dao查询时间
配置日志文件查看nginx web容器的响应时间。
8.为什么要自测,仅仅使用Postman来测试足够吗?什么是本地测试,什么是在开发环境测试?在开发过程中,应该每天部署代码到开发环境吗,为什么?
自测来决定自己写的代码功能有无问题。
如果是把项目部署到服务器,再进行postman测试,在不考虑复杂情况下,是没有问题的。
本地测试,就是在项目自己的电脑进行程序测试
开发环境测试,就是把项目部署在服务器上线进行程序测试。
应该每天都部署一遍,甚至多遍,因为开发环境更模拟真实线上情况,更容易发现程序在复杂开发环境下的一些隐藏问题。
9.保存图片有几种方式?什么样的情景下应该使用哪一种?
(1) 图片比较小的话,直接以二进制方式写入数据库(base64的形式)
(2) 图片存在本机的服务器中,然后将图片路径放入数据库
(3)保存到图片云数据库,然后将图片路径放入数据库
其中(1)直接存图片到数据库中单独的表,实际使用很少
(2)适用于本地硬盘容量足够储存业务所需图片
(3)适用于业务需要大量图片,本地服务器没有足够硬盘容量储存,保存到第三方云数据库
10.为什么要先写单元测试?单元测试应该包括哪些?在正式打包的过程中,什么样的单元测试应该被屏蔽?在Maven里用什么方法可以跳过单元测试,单元测试应该被跳过吗。
单元测试可以测试自己写的每个接口是否正确运行,能否传入参数 ,能否返回正确数据。
打包过程中,mvn打通过调用命令 mvn package -DskipTests来跳过测试打包,如果不跳过单元测试,打包会失败。
11.为什么提供假数据的时候要求,直接Controller接收请求,在JSP中写死数据返回以用做假数据?为什么提供假数据的时候要求数据完整,有分页尽可能给分页,数据尽可能真实?
因为前端一直要用假数据,jsp写死假数据, 无论代码怎么变,前端可以一直获取假数据使用
假数据目的是模拟真实的数据传输情况,所以数据应该尽可能的真实。
12.为什么要写假数据,前后端联调的时候,应该什么时候商定接口文档,接口文档应该谁来维护,如果不提供假数据,会发生什么问题?
前端页面的开发需要依赖于后端提供的数据,接口文档应该再开发初期一起商定。
接口文档由前后端一起维护,如果不提供假数据,前端无法进行下一步开发。
13.接口应该怎么定义?一个页面应该只对应一个接口吗?还是一个实体对应一个接口,让前端去组装数据?两者的使用场景是什么?
接口由业务需求定义,一个页面可以有多个接口,一个实体类也可以有多个接口。
14.多层分类应该怎么设计表结构,分别有什么问题?像文章分类这种需求,如果分类不确定,级别不确定,有可能动态调整,数据量和访问量又比较大,该怎么去设计?
15.什么是实体表,什么是关系表,一对多和多对多应该怎么设计表?
实体表就是对应一个实际对象的表,比如作品表,留言表。
关系表就是表示对象表之间关系的表,通常在表的多对多关系使用。
一对多建表, 一个作品有多个留言 ,那在留言表添加作品的主键id即可
多对多建表,新建一个关系表,设置自增id,再放入两个对象表的主键id
16.什么是外键,用处是什么,为什么不建议使用外键做关联?
外键是数据表中的约束
假设有一个A表,一个B表,B表从属A。
那把A表的主键,放到B表的表格内,A和B表就通过外键关联了。
它使得AB表之中的数据始终完整。
(在数据库层面给AB两表建立了联系,也称物理外键)
外键的作用:
保证数据的完整性和一致性(对AB表的任何 插入,修改删除等操作 都得判断主外键)
级联操作方便(级联删除, 修改A表主键值 B也跟着改)
将数据完整性判断托付给了数据库完成,减少了程序的代码量
外键的缺点:
1.性能问题(往A表插入数据还得查询B表,增加查询过程,也加大了数据库的性能消耗)
2.扩展性问题(如果修改业务,还要在数据库中修改表之间外键关系,如果牵扯很多表的话,会更麻烦)
3.并发问题(在使用外键的情况下,每次修改A表数据都需要去B表检查数据,需要获取额外的锁。若是在高并发大流量事务场景,使用外键更容易造成死锁。)
尽量多使用逻辑外键,数据库中不设置外键,只有在sql语句中才对A B表建立逻辑外键关系。 如果要更改业务,不用动数据库,更改sql语句即可。
17.什么是数据库范式,是否应该严格遵守范式,什么情况下应该不遵守范式?
前面的日报有写过数据库的三大范式。
http://www.jnshu.com/daily/110183?total=107&page=34&uid=39294&sort=0&orderBy=3
数据库的三大范式,将每个表都拆的非常细分,目的是为了消除重复数据,减少数据冗余,让数据库内的数据更好的组织,让磁盘空间得到更有效的利用。
但如果真的所有数据库都严格范式,将在无形中增加了数据表,增加了许多数据表之间的联系,导致查询更复杂,可能会需要更多连表查询。
在满足业务需求的情况下,完全可以不按照范式的规则来建立数据库表。
明天计划的事情:
开始任务4
评论