上一篇:JAVA知识点全总结——(三)多线程与并发
mysql顶层有连接池,这个类似于线程池,用来在并发的时候进行数据库的操作。当sql语句读取到Mysql中时,有一层封装层用来拆分sql语句,比在处理之后将结果返回提供给上层,做了一层封装层;在这层封装层下面是语句的过滤器,会将分段的语句过滤,如果有的地方不和语法就会报错返回;再下面是优化器,一条语句究竟用什么索引,怎么用索引,怎么去执行,在这一层会给出执行计划;在这一层还有缓存,当一条语句查询完毕后结果会存放在缓存中,如果是同样的语句那么就不会再次执行了。再下面是执行引擎,之后就是数据文件了。
B树是一种多路树,因为二叉树的搜索效率好,但是深度过深,在数据库中每一次找字节点都有可能是一次IO,所以深度对二叉树很重要,B树通过多子的规定降低了二叉树的深度。B树规定根结点的子节点个数最少为2,最多为m。这里的m是一个阶的概念,不同阶的B树不一样。非叶节点的子节点个数是2分之m到m,这样确保了树的深度不高,一页存放的信息能一次IO读取出来。
B+树和B树差不多,除了B+树为所有叶子结点增加一个链指针,而且所有关键字都在叶子结点出现。B+tree的磁盘读写代价更低,没有了中间索引,可以放下更多的数据,而且范围查找的时候从链表开始走,快的不行。
ACID是事务的四大特性,想要成为事务,必须具备这四点。事务具有一起成功一起失败的特点。Atomicity:原子性体现在对于一个事务来讲,要么一起执行成功要么一起失败,执行的过程中是不能被打断或者执行其他操作的。Consistency:一致性表现为事务进行过后和执行前,整体系统都是稳定的,比如对于入账出账操作是不会有总资金的变化的。Isolation:隔离性表示各个事务之间不会互相影响,数据库一般会提供多种级别的隔离。实际上多个事务是并发执行的,但是他们之间不会互相影响。Durability:持久性表示一旦一个事务成功了,那么他的改变是永久性的被记录和操作。
数据在读取数据的时候读到了其他事务正在进行修改的数据,其他的事务修改数据后又对它进行了其他操作或回滚了,这样读取的那个数据是错误的。
在一个事务中反复读取一个数据时读到了不同的数据,因为在读取的过程中其他的事务对其进行了修改并提交了。
第二个事务插入或删除一条数据,这个数据本应该是第一个事务读取到的,但是因为第二个事务紧接着第一个事务完成后才完成,导致了第一个事务没有读到这一条,好像出错了一样。
数据库提供了四种级别的事务隔离,来保证不同的效果。数据库锁是为了构建这些隔离级别存在的。
乐观锁是一种概念,不为数据加显示的锁,但是会维护一个版本号或者时间戳,在完成数据操作的时候会检查这个版本号,如果不大于之前获取的值则说明在此期间没有发生更新,可以完成事务。乐观锁有更好的并行性,但是在事务处理比较集中的时候失败率比较高,在事务分散的时候效率不错。而且在多服务多系统中,如果其他的服务调用了本数据库,需要在多个服务之间同步版本号的逻辑,比较复杂,耦合度高。
悲观锁的概念就是预测一定会发生并发问题,所以在代码中就使用锁来保证安全。悲观锁是对应于乐观锁的一种概念,具体的实现还有很多种。
排他锁也叫做写锁,就是严格的排他,在一个锁获得了当前的操作权后其他的任何锁都要等待他完成并释放。
共享锁也叫做读锁,多个共享锁可以一起工作,因为只是读取数据。
用来预定要对此对象施加X锁,它允许其他事务读,但不允许再施加U锁或X锁;当被读取的对象将要被更新时,则升级为X锁,主要是用来防止死锁的。因为使用共享锁时,修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为排它锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个对象申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。
均不可避免。不加锁
可以避免 :脏读。读取的时候加行级锁,读取结束释放。
可以避免 :脏读、不可重复读。读取的时候加行级锁,一直等到事务结束才会释放。
可以避免 :脏读、不可重复读、幻读。任何时候直接加表锁,事务结束释放。
create database xxx
dorp database xxx
create table tablexxx (col1 type1 primary key,
col2 type2 not null ...)
drop table tablexxx
alter table tablexxx add column col type ...
alter table tablexxx add primary key(col)
alter table tablexxx drop primary key(col)
create index idsxxx on tablexxx(col1, col2...)
drop index indexxx
select * from xxx where xxx = 'ss'
insert into tablexxx (col1, col2, ...) values(values1, values2, ...)
delete from tablexxx where xx ='xx'
update tablexxx set xx = 'xx' where xx ='xx'
select * from xx where xx orderby xx desc , xx
select count(*) as ttc where tablexxx
avg max min sum
union union all left join right join join
没有where的时候用count(*) count(*)与count(1)一样,有主键的差别。统计列的时候要求统计非空的count(列名)
group by having和select必须根据groupby的字段做调整和输出,如果select中输出了无关项,则自动输出第一条
定义:关系中的每个属性都不可再分。
理解:基本的数据库都满足第一范式。
定义:关系中不存在非主属性对于主属性的部分函数依赖。或者理解为:非主属性必须对主属性完全依赖。
举例:比如主属性为:A、B,而C作为一个非主属性,只与A有依赖关系,C与B无关,那么此时C对于A、B只存在部分依赖,此时不符合第二范式。
理解:符合第二范式的关系能够保证每一个非主属性都严格的依赖主属性。就是任何一个非主属性都必须和所有的主属性有关。通俗的说,这张表中的内容都和主键有关,主键是最核心的部分。如果存在冗余的字段,将在第二范式中被剔除。
作用:
1)消除冗余,只有完全依赖的才能留下,依赖性不强的字段都删掉了。
2)降低数据间的耦合,对一类事物的修改不会影响其他事物。
定义:关系中不存在非主属性对于非主属性的任何函数依赖。
举例:比如主属性为:A,而B、C作为非主属性,存在“B依赖A,C完全依赖或部分依赖B”的情况。那么此时C对于B存在依赖情况,此时不符合第三范式。
理解:第三范式更加严格,第二范式说普通的属性必须和主属性(如果主属性是多个,那么就必须和所有的主属性(或主属性联合起来的概念)有关)有关,但是没有规定这些普通属性间有什么要求。第三范式说,如果普通属性之间也有关系,比如C会被B决定或影响,那么C就应该被踢出去,单独和B(或含有B和其他的属性)建另外的一张表。
作用:
1)消除冗余,往往C依赖于B,当有大量B的时候C也都是大量一样的数据,浪费。
2)降低数据间的耦合,对一类事物的修改不会影响其他事物。
定义:主属性中不存在某些属性部分依赖另外一些属性。
举例:比如主属性为:A、B、C。存在B依赖于A、C的情况。此时不符合BC范式。
理解:看了第二第三范式你会发现一个问题,如果我把主属性也就是主键定义的很大,基本都能满足这两个范式,因为第二第三范式是针对非主属性的规定。范式也想到了这个问题,就出现了BC范式,通俗地说,BC范式就是告诉我们“别吧主键定太多,主键也要符合规矩啊”。主键内不能存在依赖的情况。
作用:1)降低数据间的耦合,对一类事物的修改不会影响其他事物。
如果说主要进行查询操作,那么MyISAM比较合适一些,MyISAM没有事务的概念,没有外键的概念等,写的时候加表锁。InnoDB更全面,事务、外键、主键自增等。
MVCC是多版本并发控制,相比较普通的加锁机制,MVCC用不同的版本来隔离读和写之间的冲突。每个连接到数据库的线程池实例看到的都是数据库的一个快照版本。写操作在完成前对其他读操作是不可见的,每个数据都拥有一个版本号,表示这个数据当前的版本。读取可能读取到的是过时的数据,但是这个数据不是一个错误的数据。
explain命令 查看执行计划,后面直接跟语句
mysql> explain select * from servers;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | servers | ALL | NULL | NULL | NULL | NULL | 1 | NULL |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
row in set (0.03 sec)
Extra:(Using index:使用了覆盖索引;Using where:先读取了where的条件再查行,是一种优化;Using temporary:需要临时表来存放信息;Using filesort:无法利用索引排序;Using join buffer:链接的时候没有使用索引,需要优化)
EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
EXPLAIN不考虑各种Cache
EXPLAIN不能显示MySQL在执行查询时所作的优化工作
部分统计信息是估算的,并非精确值
EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。
连接池和线程池很像,都是创建一些连接的对象放在内存里,一直维护这些,如果有请求要查询的话就使用连接池中的对象进行查询。在spring中集成c3p0之类的数据源也可以对连接池进行配置,让连接池按照我们希望的样子构建,比如可以配置最大空闲连接数、最小空闲连接数、初始化连接数、最大连接数量。
NoSQL表示的是一类非关系型的数据库,其中比较有代表性的是redis。
C表示一致性,A表示可用性,P表示分区容忍性。一般来讲这三种原则能够符合其中的两种。
BA表示基本可用性,S表示柔软性,E表示最终一致性。
redis是一种kv的数据存储系统
redis可以做很多功能,主要有数据库、缓存、消息队列等。对于缓存而言做缓存服务器,将耗时久的语句结果放入redis中,下次查询直接返回结果。高并发,大量数据访问数据库时可能出现异常,用redis缓存先接受访问请求进行处理,预防并发问题。
大量访问缓存中不存在的数据,导致直接连到数据库上出现异常,解决方法:
因为失效时间相同,缓存大面积同时失效导致直接连到数据库上出现异常,解决方法:
主要有FIFO,LRU,LFU等几种算法 - FIFO,先进先出,先进入缓存的先淘汰 - LRU,最近最少使用,最少使用的缓存先淘汰 - LRU,最近最不常用,定期之内,最不常用的先淘汰
缓存预热:新的缓存系统没有任何缓存数据,在缓存重建数据的过程中,系统性能和数据库负载都不太好,所以最好是在系统上线之前就把要缓存的热点数据加载到缓存中
缓存热备:当一台缓存服务器不可用时能实时切换到备用缓存服务器,不影响缓存使用。集群模式下,每个主节点都会有一个或多个从节点来当备用,一旦主节点挂点,从节点立即充当主节点使用
缓存更新:除了redis自带的缓存更新方法,为了降低内存使用我们可以进行其他更新方法:
定时清理过期的缓存,因为是惰性删除和定期抽样删除,定时清理还是有必要的
当用户请求时判断缓存是否过期,过期就去底层更新数据并更新缓存
缓存降级:当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级
一种是RDB持久化,原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化。
一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
另外一种是AOF(append only file)持久化,原理是将Reids的操作日志以追加的方式写入文件。
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
下一篇:JAVA知识点全总结——(五)网络