SQL Select 语句完整的执行顺序:
FROM-->ON-->OUTER (JOIN)-->WHERE-->GROUP BY-->CUTE|ROLLUP-->HAVING-->SELECT-->DISTINCT-->ORDER BY-->TOP
Mysql 数据库存储的原理
储存过程是一个可编程的函数,它在数据库中创建并保存。它可以有 SQL 语句和一些特殊的控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟。它允许控制数据的访问方式。
存储过程优点
1、存储过程能实现较快的执行速度
2、存储过程允许标准组件是编程。
3、存储过程可以用流程控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。
4、存储过程可被作为一种安全机制来充分利用。
5、存储过程能够减少网络流量
事务的特性(ACID)
1、原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执
行。
2、一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相
一致。
3、隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透
明的。
4、持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即
使数据库出现故障
隔离级别
1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
默认的事务隔离级别为repeatable-read
数据库索引
数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用 B_TREE。B_TREE 索引加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。
优化查询效率方案
- 应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索。
- 应尽量避免在 where 子句中对字段进行 null 值判断,避免使用!=或<>操作符,避免使用 or连接条件,或在 where 子句中使用参数、对字段进行表达式或函数操作,否则会导致全表扫描
- 不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
- 使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。
- 很多时候可考虑用 exists 代替 in。
- 尽量使用数字型字段。
- 尽可能的使用 varchar/nvarchar 代替 char/nchar。
- 任何地方都不要使用 select from t ,用具体的字段列表代替“”,不要返回用不到的任何字段。
- 尽量使用表变量来代替临时表。
- 避免频繁创建和删除临时表,以减少系统表资源的消耗。
- 尽量避免使用游标,因为游标的效率较差。
- 在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF。
- 尽量避免大事务操作,提高系统并发能力。
- 尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
Mysql 集群的优缺点
优点:
- 99.999%的高可用性
- 快速的自动失效切换
- 灵活的分布式体系结构,没有单点故障
- 高吞吐量和低延迟
- 可扩展性强,支持在线扩容
缺点
- 存在很多限制,比如:不支持外键
- 部署、管理、配置很复杂
- 占用磁盘空间大、内存大
- 备份和恢复不方便
- 重启的时候,数据节点将数据 load 到内存需要很长的时间
Mysql 引擎,各引擎之间区别:
主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:
- InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一
些列增删改中只要哪个出错还可以回滚还原,而 MyISAM 就不可以了; - MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
- InnoDB 支持外键,MyISAM 不支持;
- MyISAM 是默认引擎,InnoDB 需要指定;
- InnoDB 不支持 FULLTEXT 类型的索引;
- InnoDB 中不保存表的行数,如 select count() from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count()语句包含where 条件时 MyISAM 也需要扫描整个表;
- 对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM 表中可以和其他字段一起建立联合索引;清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;
- InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'
数据库的优化
1.优化索引、SQL 语句、分析慢查询;
2.设计表的时候严格根据数据库的设计范式来设计数据库;
3.使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘 IO
4.优化硬件;采用 SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等
5.采用 MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率;
6.垂直分表;把一些不经常读的数据放在一张表里,节约磁盘 I/O;
7.主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来;
8.分库分表分机器(数据量特别大),主要的的原理就是数据路由;
9.选择合适的表引擎,参数上的优化
10.进行架构级别的缓存,静态化和分布式;
11.不采用全文索引;
12.采用更快的存储方式,例如 NoSQL 存储经常访问的数据。
Mysql 数据库分区、分表
分表可以通过三种方式:Mysql 集群、自定义规则和 merge 存储引擎。
分区有四类:
- RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。
- LIST 分区:类似于按 RANGE 分区,区别在于 LIST 分区是基于列值匹配一个离散值集合中的某个值来进行选择。
- HASH 分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算。这个函数可以包含 MySQL 中有效的、产生非负整数值的任何表达式。
- KEY 分区:类似于按 HASH 分区,区别在于 KEY 分区只支持计算一列或多列,且 MySQL 服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
Sql 注入是产生原因及防止措施?
程序开发过程中不注意规范书写 sql 语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST 和 GET 提交一些 sql 语句正常执行。产生 Sql 注入。下面是防止办法:
- 过滤掉一些常见的数据库操作关键字,或者通过系统函数来进行过滤。
- 在 PHP 配置文件中将 Register_globals=off;设置为关闭状态
- SQL 语句书写的时候尽量不要省略小引号(tab 键上面那个)和单引号
- 提高数据库命名技巧,对于一些重要的字段根据程序的特点命名,取不易被猜到的
- 对于常用的方法加以封装,避免直接暴漏 SQL 语句
- 开启 PHP 安全模式:Safe_mode=on;
- 打开 magic_quotes_gpc 来防止 SQL 注入
- 控制错误信息:关闭错误提示信息,将错误信息写到系统日志。
- 使用 mysqli 或 pdo 预处理。
非关系型数据库与关系型数据库区别
- SQL 数据存在特定结构的表中;而 NoSQL 则更加灵活和可扩展,存储方式可以省是 JSON 文档、哈希表或者其他方式。
- 在 SQL 中,必须定义好表和字段结构后才能添加数据,例如定义表的主键(primary key),索引(index),触发器(trigger),存储过程(stored procedure)等。表结构可以在被定义之后更新,但是如果有比较大的结构变更的话就会变得比较复杂。在 NoSQL 中,数据可以在任何时候任何地方添加,不需要先定义表。
- SQL 中如果需要增加外部关联数据的话,规范化做法是在原表中增加一个外键,关联外部数据表。而在 NoSQL 中除了这种规范化的外部数据表做法以外,我们还能用如下的非规范化方式把外部数据直接放到原数据集中,以提高查询效率。缺点也比较明显,更新审核人数据的时候将会比较麻烦。
- SQL 中可以使用 JOIN 表链接方式将多个关系数据表中的数据用一条简单的查询语句查询出来。NoSQL 暂未提供类似 JOIN 的查询方式对多个数据集中的数据做查询。所以大部分 NoSQL 使用非规范化的数据存储方式存储数据。
- SQL 中不允许删除已经被使用的外部数据,而 NoSQL 中则没有这种强耦合的概念,可以随时删除任何数据。
- SQL 中如果多张表数据需要同批次被更新,即如果其中一张表更新失败的话其他表也不能更新成功。这种场景可以通过事务来控制,可以在所有命令完成后再统一提交事务。而 NoSQL 中没有事务这个概念,每一个数据集的操作都是原子级的。
- 在相同水平的系统设计的前提下,因为 NoSQL 中省略了 JOIN 查询的消耗,故理论上性能上是优于 SQL 的。
数据库负载均衡
负载均衡集群是由一组相互独立的计算机系统构成,通过常规网络或专用网络进行连接,由路由器衔接在一起,各节点相互协作、共同负载、均衡压力,对客户端来说,整个群集可以视为一台具有超高性能的独立服务器。
实现原理
实现数据库的负载均衡技术,首先要有一个可以控制连接数据库的控制端。在这里,它截断了数据库和程序的直接连接,由所有的程序来访问这个中间层,然后再由中间层来访问数据库。这样,我们就可以具体控制访问某个数据库了,然后还可以根据数据库的当前负载采取有效的均衡策略,来调整每次连接到哪个数据库。
实现多据库数据同步
对于负载均衡,最重要的就是所有服务器的数据都是实时同步的。这是一个集群所必需的,因为,如果数不据实时、不同步,那么用户从一台服务器读出的数据,就有别于从另一台服务器读出的数据,这是不能允许的。所以必须实现数据库的数据同步。这样,在查询的时候就可以有多个资源,实现均衡。比较常用的方法是 Moebius for SQL Server 集群,Moebius for SQL Server 集群采用将核心程序驻留在每个机器的数据库中的办法,这个核心程序称为 Moebius for SQL Server中间件,主要作用是监测数据库内数据的变化并将变化的数据同步到其他数据库中。数据同步完成后客户端才会得到响应,同步过程是并发完成的,所以同步到多个数据库和同步到一个数据库的时间基本相等;另外同步的过程是在事务的环境下完成的,保证了多份数据在任何时刻数据的一致性。正因为 Moebius 中间件宿主在数据库中的创新,让中间件不但能知道数据的变化,而且知道引起数据变化的 SQL 语句,根据 SQL 语句的类型智能的采取不同的数据同步的策略以保证数据同步成本的最小化。
数据条数很少,数据内容也不大,则直接同步数据。数据条数很少,但是里面包含大数据类型,比如文本,二进制数据等,则先对数据进行压缩然后再同步,从而减少网络带宽的占用和传输所用的时间。
数据条数很多,此时中间件会拿到造成数据变化的 SQL 语句, 然后对 SQL 语句进行解析,分析其执行计划和执行成本,并选择是同步数据还是同步 SQL 语句到其他的数据库中。此种情况应用在对表结构进行调整或者批量更改数据的时候非常有用。
优点
1.扩展性强:当系统要更高数据库处理速度时,只要简单地增加数据库服务器就 可以得到扩展。
- 可维护性:当某节点发生故障时,系统会自动检测故障并转移故障节点的应用,保证数据库的持续工作。
- 安全性:因为数据会同步的多台服务器上,可以实现数据集的冗余,通过多份数据来保证安全性。另外它成功地将数据库放到了内网之中,更好地保护了数据库的安全性。
4.易用性:对应用来说完全透明,集群暴露出来的就是一个 IP
缺点
1.不能够按照 Web 服务器的处理能力分配负载。
- 负载均衡器(控制端)故障,会导致整个数据库系统瘫痪。
数据库的设计三范式
第一范式:数据库表的每一列都是不可分割的原子数据项,即列不可拆分。
第二范式:建立在第一范式的基础上,要求数据库表中的每个实例或记录必须是可以唯一被区分的,即唯一标识。
第三范式:建立在第二范式的基础上,任何非主属性不依赖与其他非主属性,即引用主键。
存储过程和函数的区别
相同点:
存储过程和函数都是为了可重复的执行操作数据库的 sql 语句的集合。
- 存储过程和函数都是一次编译,就会被缓存起来,下次使用就直接命中已经编译好的 sql 语句,不需要重复使用。减少网络交互,减少网络访问流量。
不同点:
标识符不同,函数的标识符是 function,存储过程是 proceduce。
- 函数中有返回值,且必须有返回值,而过程没有返回值,但是可以通过设置参数类型(in,out)来实现多个参数或者返回值。
- 存储函数使用 select 调用,存储过程需要使用 call 调用。
- select 语句可以在存储过程中调用,但是除了 select..into 之外的 select 语句都不能在函数中使用。
- 通过 in out 参数,过程相关函数更加灵活,可以返回多个结果。
Mysql 日志
错误日志:记录启动,运行或者停止 mysql 时出现的问题;
通用日志:记录建立的客户端连接和执行的语句;
二进制日志:记录所有更改数据的语句;
慢查询日志:记录所有执行时间超过 long_query_time 秒的查询或者不适用索引的查询)
通过使用--slow_query_log[={0|1}]选项来启用慢查询日志,所有执行时间超多 long_query_time 的语句都会被记录。
Redis 集群搭建
这篇文章写的不错,参考此博客
https://blog.csdn.net/yfkiss/article/details/38944179
Redis 的并发竞争问题解决方案
1.可以使用独占锁的方式,类似操作系统的 mutex 机制,不过实现相对复杂,成本较高。
2.使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)
- 本质上是假设不会进行冲突,使用 redis 的命令 watch 进行构造条件
MySQL 和 Redis 高可用性体现
1.MySQL Replication 是 MySQL 官方提供的主从同步方案,用于将一个 MySQL 实例的数据,同步到另一个实例中。Replication 为保证 数据安全做了重要的保证,也是现在运用最广的MySQL容灾方案。Replication用两个或以上的实例搭建了MySQL主从复制集群,提供 单点写入,多点读取的服务,实现了读的 scale out。
2.Sentinel 是 Redis 官方为集群提供的高可用解决方案。在实际 项目中可以使用 sentinel去做 Redis 自动故障转移,减少人工介入的工作量。另外 sentinel 也给客户端提供了监控消息的通知,这样客户端就可根据消息类型去判断服务器的状态,去做对应的适配操作。
下面是 Sentinel 主要功能列表:
- Monitoring:Sentinel 持续检查集群中的 master、slave 状态,判断是否存活。
- Notification:在发现某个 Redis 实例死的情况下,Sentinel 能通过 API 通知系统管理员或其他程序脚本。
- Automatic failover:如果一个 master 挂掉后,sentinel 立马启动故障转移,把某个 slave 提升为 master。其他的 slave 重新配置指向新 master。
- Configuration provider:对于客户端来说 sentinel 通知是有效可信赖的。客户端会连接sentinel 去请求当前 master 的地址,一旦发生故障 sentinel 会提供新地址给客户端。