MySQL高级部分(二)

鉴于数据库(一)的知识点,我们再补充一些关于数据库结构优化以及索引支持的相关知识点。

##数据库结构优化介绍
首先要说为什么要结构优化呢?

1.减少数据的冗余。
2.尽量避免数据库维护中出现的更新,插入和删除操作。
    插入:如果表中的某个实体随另一个实体的存在而存在
        (例如学生信息,如果你只给学生的姓名而没有学号就不能添加进学生管理系统)
    更新:如果更改表中的某个实体的单独属性时,需要对多行同时更新。
        (类似于选修课,如果课程时间变动,那么选课的同学都要变动)
    删除:如果删除一个实体,则会导致其他实体的消失
        (选课后课程被取消)
3.节约数据库存储空间。
4.提高查询效率。

数据库结构设计(步骤)

1.需求分析:全面了解产品设计的存储需求,数据库处理需求,安全性以及完整性的需求。
2.逻辑设计:设计数据库的逻辑存储结构,数据实体间的逻辑关系,解决数据冗余问题和维护异常。
3.物理设计:根据所适用的数据库特点进行表结构设计。
4.维护优化:根据实际情况对索引、存储结构进行优化。

数据库设计范式(遵循三范式)

* 概念:设计数据库时,需要遵循的一些规范。要遵循后边的范式要求,必须先遵循前边的所有范式要求

    设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
    目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。

* 分类:
    1. 第一范式(1NF):每一列都是不可分割的原子数据项,单一属性的列都是由基本数据类型构成,设计出来的表都是二维表
    2. 第二范式(2NF):在1NF的基础上,非码属性必须完全依赖于码(在1NF基础上消除非主属性对主码的部分函数依赖)
        * 几个概念:
            1. 函数依赖:A-->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值。则称B依赖于A
                例如:学号-->姓名。  (学号,课程名称) --> 分数
            2. 完全函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定需要依赖于A属性组中所有的属性值。
                例如:(学号,课程名称) --> 分数
            3. 部分函数依赖:A-->B, 如果A是一个属性组,则B属性值得确定只需要依赖于A属性组中某一些值即可。
                例如:(学号,课程名称) -- > 姓名
            4. 传递函数依赖:A-->B, B -- >C . 如果通过A属性(属性组)的值,可以确定唯一B属性的值,在通过B属性(属性组)的值可以确定唯一C属性的值,则称 C 传递函数依赖于A
                例如:学号-->系名,系名-->系主任
            5. 码:如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性(属性组)为该表的码
                例如:该表中码为:(学号,课程名称)
                * 主属性:码属性组中的所有属性
                * 非主属性:除过码属性组的属性

    3. 第三范式(3NF):在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除了非主属性对主键的传递依赖)

需求分析和逻辑设计

例如现在要按照以下要求设计一个电子商务网站的数据库结构:

1.本网站只销售图书类商品
2.需要具有以下的功能:
    用户登录----商品展示----供应商管理
    用户管理----商品管理----在线销售

用户登录功能:

1.用户必须注册并登录系统才能进行网上交易。(因此需要一个不同的账号作为主键)
2.同一时间一个用户只能登录一个地方。
3.用户信息:{用户名,密码,手机号,姓名,注册日期,在线状态,出生日期等}

首先呢设计商品展示以及商品管理功能

商品信息:{商品名称,分类名称,出版社名称,图书价格,图书描述,作者}

由此可见,把所有信息都冗杂在一条数据库中会造成很多不必要的写入写出,也许一本书有很多的描述我仅仅想展示一个,这样我们就要设计新的数据库表格。

商品信息:{商品名称,出版社名称,图书价格,图书描述,作者}
分类信息:{分类名称,分类描述}
商品分类(对应关系表):{商品名称,分类名称}

其次我们还要设计在线销售功能:

在线销售:{订单编号,下点用户名,下单日期,订单金额,订单商品分类,订单商品名,订单商品单价,订单商品数量,支付金额,物流单号}

可以看到
    1.只有一个业务主键,符合第二范式
    2.订单编号,订单商品单价,订单商品数量 存在着传递依赖关系,不符合第三范式,
    3.数据冗余(订单商品信息和商品信息表中数据)

所以要更改数据表:
订单表:{订单编号,下点用户名,下单日期,支付金额,物流单号}
订单商品关联表:{订单编号,订单商品分类,订单商品名,订单商品数量}

供应商管理功能:

信息:{出版社名称,地址,电话,联系人,银行账户}

同时还要编写符合规范的SQL语句,但是完全符合范式化的设计有时候并不能得到良好的SQL查询性能,因此我们还需要反范式化设计。

例如下单用户就是商品的收货人,那么我们在发货之前一定要查询出每个订单的下单人信息,而这些信息全部记录在用户信息表中,显然我们要执行的读操作过多,从而减小了一定的效率。那么我们就来看看什么是反范式化设计:

反范式化是针对范式化而言的,就是为了性能和读取效率的考虑而适当对数据库设计范式要求进行违反,而允许存在少量数据冗余,换句话说,就是牺牲空间换取时间。

因此我们来探讨以下范式的优缺点:

优点:
    1.可以尽量的减少数据的冗余(根本优点)
    2.更新操作比反范式化更快。
    3.表通常比反范式化更小。
缺点:
    1.对查询需要对多个表进行关联(这样简化了写但是读取更耗时,因为大多数都是读取操作)
    2.这样更难进行索引优化

那么反范式化的优缺点又是什么呢?

优点:
    1.减少表的关联。
    2.更好的进行索引优化。(其实就是优缺点互换)
缺点:
    1.数据冗余以及数据维护异常比较困难。
    2.对数据修改需要更多的成本。

物理设计

根据所选择的关系型数据库的特点,对逻辑模型进行存储结构设计。

1.定义数据库、表、以及字段的命名规范。
(因为有可能是多人协作完成,为了一致性)
2.选择合适的存储引擎。
3.为表中的字段选择合适的数据模型。
4.建立数据库结构。
当然了,合适额的数据库模型只当一个列可以选择多种数据库结构类型时候,应该有限考虑“数字”类型,其次是“日期”“二进制”,最后是“字符型”
对于同级别的数据类型,应该有限占用用剑小的数据类型。

char和carchar的区别

VARCHAR比CHAR节省空间,在效率上比CHAR会稍微差一些,即要想获得效率,就必须牺牲一定的空间,这也就是我们在数据库设计上常说的‘以空间换效率’。

VARCHAR2虽然比CHAR节省空间,但是如果一个VARCHAR列经常被修改,而且每次被修改的数据的长度不同,这会引起‘行迁移’(Row Migration)现象,而这造成多余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用CHAR代替VARCHAR会更好一些。

MySQL复制功能

提供分担“读负载”的功能,主要是通过备库来分担此功能。为了高可用以及灾难恢复,备份提供了更多更好的选择。

首先要了解以下复制解决了什么问题:

1.实现在不同的服务器上数据的分布。
2.实现数据读取的负载均衡。
3.增强数据读取的安全性
4.实现数据库高可用和故障的切换保证服务器不会一时宕机。
5.实现数据库在线升级操作。

MySQL的二进制日志

记录所有对MySQL数据库的修改时间,包括增删改查操作事件以及对表结构的修改。因为记录量相对较小,所以节约了磁盘和网络的IO。

##高可用架构
如何实现高可用呢?

避免系统用不可以的因素,减少系统不可用的时间。例如服务器的磁盘耗尽,或者是糟糕的SQL语句以及表结构和索引没有优化,亦或者是主从服务器的不一致等待。所以:

1.建立完善的监控和报警机制系统。
2.对被扽数据库进行恢复测试。
3.正确配置数据库环境,对于某些从数据库设置只读即可。
4.对不需要的数据库进行归档和清理。

哪究竟如何实现呢?

增加系统冗余,保证发生系统不可以时间尽快恢复。
    1.避免单点故障
    2.主从切换以及故障转移。

哪怎么解决单点故障呢?

首先我们还要了解一下什么是单点故障:指一个系统中提供相同功能的组件只有一个,如果这个组件失效了,就会影响整个系统功能的正常使用。解决方法:

1.利用SUN存储或者DRDB磁盘复制解决。
2.利用多写集群或者NDB集群解决。
3.利用MySQL的主从复制解决。

MMM架构

MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序。MMM使用Perl语言开发,主要用来监控和管理MySQL Master-Master(双主)复制,虽然叫做双主复制,但是业务上同一时刻只允许对一个主进行写入,另一台备选主上提供部分读服务,以加速在主主切换时刻备选主的预热,可以说MMM这套脚本程序一方面实现了故障切换的功能,另一方面其内部附加的工具脚本也可以实现多个slave的read负载均衡。

MMM提供了自动和手动两种方式移除一组服务器中复制延迟较高的服务器的虚拟ip,同时它还可以备份数据,实现两节点之间的数据同步等。由于MMM无法完全的保证数据一致性,所以MMM适用于对数据的一致性要求不是很高,但是又想最大程度的保证业务可用性的场景。对于那些对数据的一致性要求很高的业务,非常不建议采用MMM这种高可用架构。

MHA架构

MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提升的高可用软件。在MySQL故障切换过程中,MHA能做到在0~30秒之内自动完成数据库的故障切换操作,并且在进行故障切换的过程中,MHA能在最大程度上保证数据的一致性,以达到真正意义上的高可用。

该软件由两部分组成:MHA Manager(管理节点)和MHA Node(数据节点)。MHA Manager可以单独部署在一台独立的机器上管理多个master-slave集群,也可以部署在一台slave节点上。MHA Node运行在每台MySQL服务器上,MHA Manager会定时探测集群中的master节点,当master出现故障时,它可以自动将最新数据的slave提升为新的master,然后将所有其他的slave重新指向新的master。整个故障转移过程对应用程序完全透明。

在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5的半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数据一致性。

目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即一台充当master,一台充当备用master,另外一台充当从库,因为至少需要三台服务器,出于机器成本的考虑,淘宝也在该基础上进行了改造,目前淘宝TMHA已经支持一主一从。(出自:《深入浅出MySQL(第二版)》)

读写分离和负载均衡

1.程序实现负载均衡:
    优点:
        有开发人员自己控制,较为灵活,而且性能消耗比较小。
    缺点:
        增加开发人员的压力以及代码的复杂性,并且人为书写容易出错。
2.使用中间件实现:
    优点:
        由中间件分析,自动完成读写分离,可以对已有程序不做调整。
    缺点:
        增加中间层对查询效率有一定损耗,对于延迟敏感的业务没办法自动在主库执行。

什么是负载均衡呢?

主要解决的是具有相同角色的数据库,如何共同分担相同的负载问题。

感谢您的鼓励.如果喜欢可以送我一包辣条。