数据库的三范式 第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解; 第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性; 第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。 SQL执行顺序 关键字:select、from、join、on、where、group by、having、order by、distinct执行顺序 from > join > on > where > group by > having > select > distinct > order by UNION/ALL、EXCEPT/ALL和INTERSECT/ALL UNION/ALL:组合多个结果表,并消去表中重复行,和ALL一起使用时,不消除重复行。 EXCEPT/ALL:在table1中但不在table2中的行并消除重复行,和ALL一起使用时,不消除重复行。 INTERSECT/ALL:包括table1和table2中都有的行并消除重复行,和ALL一起使用时,不消除重复行。 内连接、外连接、笛卡儿积(交叉连接) 内连接:结果仅包含符合连接条件的两表中的行 外连接:结果包含符合条件的行,同时包含不符合条件的行(分为左外连接、右外连接和全外连接) 左外连接:左表全部行+右表匹配的行,如果左表中某行在右表中没有匹配的行,则显示NULL。 右外连接:右表全部行+左表匹配的行。 全外连接:全外连接:不管匹配不匹配,全部显示出来。 交叉连接:返回左表中所有行与右表中所有行的组合,也称笛卡尔积。 VARCHAE和CHAR的区别 CHAR:指定长度,如果一个数据实际长度比设定长度短,那么它将按照设定(最长)长度储存,不足部分,填补空格。适用于固定长度的字段,如性别、手机号等。 VARCHAE:指定最大长度,但该长度可变,即如果数据的实际长度比设定长度短,那么它将按照实际长度储存,而不占用剩余的空间。 适用于非固定长度的字段,如姓名、城市名等。 DROP,DELETE与TRUNCATE的区别 DROP直接删掉表 。 TRUNCATE删除表中数据,再插入时自增长id又从1开始 。 DELETE删除表中数据,可以加WHERE字句。 数据库事务(ACID) 原子性(Atomicity)一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。 一致性(Consistency)数据库总是从一个一致性的状态转换到另一个一致性的状态。 隔离性(Isolation)一个事务所做的修改在最终提交以前,对其他事务是不可见的。 持久性(Durability)一旦事务提交,则其所做的修改不会永久保存到数据库。 数据库的乐观锁和悲观锁 悲观锁:对数据被外界修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。(悲观锁的实现,往往依靠数据库提供的锁机制) 乐观锁:大多是基于数据版本 ( Version )记录机制实现。 即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据 脏读、虚读和不可重复读 脏读:一个事务读取到了另外一个事务没有提交的数据;(修改的数据还未提交就被另一个事务使用这个数据) 不可重复读:在同一事务中,两次读取同一数据,得到内容不同;(两次读取同一数据之间,另一个事务对数据进行了修改) 虚度:同一事务中,用同样的操作读取两次,得到的记录数不相同;(两次相同的操作之间,另一个事务对数据进行了新增或删除) MySQL中的四种事务隔离级别 序列化 (Serializable):可避免脏读、不可重复读、幻读的发生。 可重复读 (Repeatable read):可避免脏读、不可重复读的发生。 读已提交(Read committed):可避免脏读的发生。 读未提交 (Read uncommitted):最低级别,任何情况都无法保证。 MVCC(多版本并发控制) MVCC最大的好处:读不加锁,读写不冲突。 1.多版本并发控制(MVCC)是一种用来解决读-写冲突的无锁并发控制,也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照。 这样在读操作不用阻塞写操作,写操作不用阻塞读操作的同时,避免了脏读和不可重复读 2.当MVCC数据库更新一条数据时,不会直接重写原始的数据,而是修改新创建的数据副本。因此会有多个版本的数据被保存下来。每个事务看到的数据版本依赖于隔离级别的实现。MVCC里最通用的隔离级别的实现就是快照隔离。在快照隔离的情况下,事务只会获取到数据的在事务开始前的状态。 MYSQL主从复制 概念解释 MySQL的Replication(英文为复制)是一个多MySQL数据库做主从同步的方案,特点是异步复制。 MySQL Replication 就是从服务器拉取主服务器上的二进制日志文件,然后再将日志文件解析成相应的SQL语句在从服务器上重新执行一遍主服务器的操作,通过这种方式来保证数据的一致性。主从复制原理 1.master(主)在执行sql之后,记录二进制log文件(bin-log)。 2.slave(从)连接master,并从master获取binlog,存于本地relay-log中,然后从上次记住的位置起执行SQL语句,一旦遇到错误则停止同步。 简记:MySQL的主从复制,实际上就是Master记录自己的执行日志binlog,然后发送给Slave,Slave解析日志并执行,来实现数据复制。主服务器流程分析 首先bin-log日志文件加锁,然后读取更新的操作,读取完毕以后将锁释放掉,最后将读取的记录发送给从服务器。从服务器流程分析 在一次主从复制过程中需要用到三个线程:Binlog dump 线程、Slave I/O 线程和Slave SQL线程,其中Binlog dump 线程在主服务器上面,剩下的两个线程是在从服务器上面工作的。 这两个线程在从服务器上面的工作流程如下图所示:如何提高Mysql主从复制的效率? 1.master 端 master端有2个参数可以控制。 Binlog_Do_DB : 设定哪些数据库需要记录Binlog。 Binlog_Ignore_DB : 设定哪些数据库不要记录Binlog。 2.slave 端 slave端有6个参数可以控制。 Replicate_Do_DB : 设定须要复制的数据库,多个DB用逗号分隔。 Replicate_Ignore_DB : 设定可以忽略的数据库。 Replicate_Do_Table : 设定须要复制的Table。 Replicate_Ignore_Table : 设定可以忽略的Table。 Replicate_Wild_Do_Table : 功能同Replicate_Do_Table,但可以带通配符来进行设置。 Replicate_Wild_Ignore_Table : 功能同Replicate_Ig-nore_Table,可带通配符设置。 数据库的分库分表 分表 对于访问极为频繁且数据量巨大的单表来说,我们首先要做的就是减少单表的记录条数,以便减少数据查询所需要的时间,提高数据库的吞吐,这就是所谓的分表! 将原有的单表分为256个表 算法 :user_id%256 拆分后表的数量一般为2的n次方,就是上面拆分成256张表的由来!分库 分表能够解决单表数据量过大带来的查询效率下降的问题,但是,却无法给数据库的并发处理能力带来质的提升。面对高并发的读写访问,对数据库进行拆分,从而提高数据库写入能力,这就是所谓的分库! 将原有的单库分为256个库 算法 :user_id%256分库分表 有时数据库可能既面临着高并发访问的压力,又需要面对海量数据的存储问题,这时需要对数据库既采用分表策略,又采用分库策略,以便同时扩展系统的并发处理能力,以及提升单表的查询性能,这就是所谓的分库分表。 一种分库分表的路由策略如下: 1. 中间变量 = user_id % (分库数量 * 每个库的表数量) 2. 库 = 取整数 (中间变量 / 每个库的表数量) 3. 表 = 中间变量 % 每个库的表数量举例: 假设将原来的单库单表order拆分成256个库,每个库包含1024个表,那么按照前面所提到的路由策略,对于user_id=262145 的访问,路由的计算过程如下: 1. 中间变量 = 262145 % (256 * 1024) = 1 2. 库 = 取整 (1/1024) = 0 3. 表 = 1 % 1024 = 1 这就意味着,对于user_id=262145 的订单记录的查询和修改,将被路由到第0个库的第1个order_1表中执行!!! 数据库SQL优化 1. 对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。2. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。如:select id from t where num is null 聚集索引和非聚集索引 聚集索引 聚集索引就是存放的物理顺序和列中的顺序一样。一般设置主键索引就为聚集索引。 一个没加主键的表,它的数据无序的放置在磁盘存储器上,一行一行的排列的很整齐。如果给表上了主键,那么表在磁盘上的存储结构就由整齐排列的结构转变成了树状结构,也就是平衡树结构,换句话说,就是整个表就变成了一个索引,也就是所谓的聚集索引。 这就是为什么一个表只能有一个主键, 一个表只能有一个聚集索引,因为主键的作用就是把表的数据格式转换成索引(平衡树)的格式放置。 上图就是带有主键的表(聚集索引)的结构图。其中树的所有结点(底部除外)的数据都是由主键字段中的数据构成,也就是通常我们指定主键的id字段。最下面部分是真正表中的数据。 假如我们执行一个SQL语句:select * from table where id = 1256 首先根据索引定位到1256这个值所在的叶结点,然后再通过叶结点取到id等于1256的数据行。 这里不讲解平衡树的运行细节, 但是从上图能看出,树一共有三层, 从根节点至叶节点只需要经过三次查找就能得到结果。如下图 然而, 事物都是有两面的, 索引能让数据库查询数据的速度上升, 而使写入数据的速度下降,原因很简单的, 因为平衡树这个结构必须一直维持在一个正确的状态, 增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构, 因此,在每次数据改变时, DBMS必须去重新梳理树(索引)的结构以确保它的正确,这会带来不小的性能开销,也就是为什么索引会给查询以外的操作带来副作用的原因。非聚集索引 讲完聚集索引 , 接下来聊一下非聚集索引, 也就是我们平时经常提起和使用的常规索引。 非聚集索引和聚集索引一样, 同样是采用平衡树作为索引的数据结构。索引树结构中各节点的值来自于表中的索引字段, 假如给user表的name字段加上索引 , 那么索引就是由name字段中的值构成,在数据改变时, DBMS需要一直维护索引结构的正确性。如果给表中多个字段加上索引 , 那么就会出现多个独立的索引结构,每个索引(非聚集索引)互相之间不存在关联。 如下图 每次给字段建一个新索引, 字段中的数据就会被复制一份出来, 用于生成索引。 因此, 给表添加索引,会增加表的体积, 占用磁盘存储空间。 非聚集索引和聚集索引的区别在于: 通过聚集索引可以一次查到需要查找的数据, 而通过非聚集索引第一次只能查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据。 聚集索引一张表只能有一个,而非聚集索引一张表可以有多个。 索引是什么?有什么作用以及优缺点? 索引是什么? 数据库引擎MyISAM和InnoDB InnoDB是非事务的存储引擎;适合用于频繁查询的应用;表锁,不会出现死锁;适合小数据,小并发 InnoDB是支持事务的存储引擎;合于插入和更新操作比较多的应用;设计合理的话是行锁(最大区别就在锁的级别上);适合大数据,大并发。 MyISAM表的数据文件和索引文件是自动分开的;InnoDB的数据和索引是存储在同一个表空间里面,但可以有多个文件组成。 为什么MyISAM会比InnoDB的查询速度快 1.InnoDB要缓存数据块,而MyISAM只缓存索引块 2.InnoDB寻址要映射到块,再到行,MyISAM记录的直接是文件的OFFSET,定位比InnoDB要快 3.InnoDB还需要维护MVCC一致 慢查询日志 慢查询日志概念 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为10,意思是运行10S以上的语句。默认情况下,Mysql数据库并不启动慢查询日志,需要我们手动来设置这个参数,当然,如果不是调优需要的话,一般不建议启动该参数,因为开启慢查询日志会或多或少带来一定的性能影响。慢查询日志支持将日志记录写入文件,也支持将日志记录写入数据库表。慢查询日志相关参数slow_query_log :是否开启慢查询日志,1表示开启,0表示关闭。log-slow-queries :旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.logslow-query-log-file:新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省的文件host_name-slow.loglong_query_time :慢查询阈值,当查询时间多于设定的阈值时,记录日志。log_queries_not_using_indexes:未使用索引的查询也被记录到慢查询日志中(可选项)。log_output:日志存储方式。log_output='FILE'表示将日志存入文件,默认值是'FILE'。慢查询日志配置 默认情况下slow_query_log的值为OFF,表示慢查询日志是禁用的,可以通过设置slow_query_log的值来开启。mysql> show variables like '%slow_query_log%';+---------------------+------------------------------------------+| Variable_name | Value |+---------------------+------------------------------------------+| slow_query_log | OFF || slow_query_log_file | /usr/local/mysql/data/localhost-slow.log |+---------------------+------------------------------------------+2 rows in set (0.00 sec) mysql> set global slow_query_log=1;Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%slow_query_log%';+---------------------+------------------------------------------+| Variable_name | Value |+---------------------+------------------------------------------+| slow_query_log | ON || slow_query_log_file | /usr/local/mysql/data/localhost-slow.log |+---------------------+------------------------------------------+2 rows in set (0.00 sec)#使用set global slow_query_log=1开启了慢查询日志只对当前数据库生效,MySQL重启后则会失效。如果要永久生效,就必须修改配置文件my.cnf(其它系统变量也是如此) 修改my.cnf文件,增加或修改参数slow_query_log 和slow_query_log_file后,然后重启MySQL服务器。slow_query_log =1slow_query_log_file=/usr/local/mysql/data/localhost-slow.logmysql> show variables like 'slow_query%';+---------------------+---------------------+| Variable_name | Value |+---------------------+---------------------+| slow_query_log | ON || slow_query_log_file | /usr/local/mysql/data/localhost-slow.log |+---------------------+---------------------+2 rows in set (0.00 sec) mysql> #慢查询的参数slow_query_log_file ,它指定慢查询日志文件的存放路径,系统默认会给一个缺省的文件host_name-slow.log日志分析工具mysqldumpslow 在实际生产环境中,如果要手工分析日志,查找、分析SQL,显然是个体力活,MySQL提供了日志分析工具mysqldumpslow得到返回记录集最多的10个SQL。mysqldumpslow -s r -t 10 /database/mysql/mysql06_slow.log 得到访问次数最多的10个SQLmysqldumpslow -s c -t 10 /database/mysql/mysql06_slow.log 得到按照时间排序的前10条里面含有左连接的查询语句。mysqldumpslow -s t -t 10 -g “left join” /database/mysql/mysql06_slow.log 另外建议在使用这些命令时结合 | 和more 使用 ,否则有可能出现刷屏的情况。mysqldumpslow -s r -t 20 /mysqldata/mysql/mysql06-slow.log | more XSS、SQL和CSRF攻击 XSS(Cross Site Script,跨站脚本攻击)是向网页中注入恶意脚本在用户浏览网页时在用户浏览器中执行恶意脚本的攻击方式。 防止方法:做数据校验、做标签转换,如:空格 转化为 。 SQL注入攻击是注入攻击最常见的形式,当服务器使用请求参数构造SQL语句时,恶意的SQL被嵌入到SQL中交给数据库执行; 防止方法:输入校验、sql不要动态拼接,用参数化的sql。 CSRF攻击(Cross Site Request Forgery,跨站请求伪造)是攻击者通过跨站请求,以合法的用户身份进行非法操作(如转账或发帖等)。 CSRF的原理是利用浏览器的Cookie或服务器的Session,盗取用户身份; 防止方法:使用post代替get,因为post不会被缓存;每次清除掉cookie。 |
|