MySQL学习日志十五,规范化数据库设计

Posted yzx-sir

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL学习日志十五,规范化数据库设计相关的知识,希望对你有一定的参考价值。

一、为什么需要数据库设计?

当数据库比较复杂时我们需要设计数据库

糟糕的数据库设计 :

  • 数据冗余,存储空间浪费

  • 数据更新和插入的异常

  • 程序性能差

良好的数据库设计 :

  • 节省数据的存储空间

  • 能够保证数据的完整性

  • 方便进行数据库应用系统的开发

软件项目开发周期中数据库设计 :

  • 需求分析阶段: 分析客户的业务和数据处理需求

  • 概要设计阶段:设计数据库的E-R模型图 , 确认需求信息的正确和完整.

  • 设计数据库步骤

收集信息

  • 与该系统有关人员进行交流 , 座谈 , 充分了解用户需求 , 理解数据库需要完成的任务.

    • 标识实体[Entity]

      • 标识数据库要管理的关键对象或实体,实体一般是名词
  • 标识每个实体需要存储的详细信息[Attribute]

  • 标识实体之间的关系[Relationship]

二、三大范式
问题 : 为什么需要数据规范化?

不合规范的表设计会导致的问题:

  • 信息重复

  • 更新异常

  • 插入异常

    • 无法正确表示信息
  • 删除异常

    • 丢失有效信息

三大范式

第一范式 (1st NF)

第一范式的目标是确保每列的原子性,如果每列都是不可再分的最小数据单元,则满足第一范式

第二范式(2nd NF)

第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。

第二范式要求每个表只描述一件事情

第三范式(3rd NF)

如果一个关系满足第二范式,并且除了主键以外的其他列都不传递依赖于主键列,则满足第三范式.

第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。

规范化和性能的关系

为满足某种商业目标 , 数据库性能比规范化数据库更重要

在数据规范化的同时 , 要综合考虑数据库的性能

通过在给定的表中添加额外的字段,以大量减少需要从中搜索信息所需的时间

通过在给定的表中插入计算列,以方便查询

本文摘抄至公众号 :狂神说

我的MYSQL学习心得(十五) 日志

这一篇《我的MYSQL学习心得(十五)》将会讲解MYSQL的日志

MYSQL里的日志主要分为4类,使用这些日志文件,可以查看MYSQL内部发生的事情。

分别是

1、错误日志:记录mysql服务的启动、运行、停止mysql服务时出现的问题  error log

2、查询日志:记录建立的客户端连接和执行的语句 gerenal log

3、二进制日志:记录所有更改数据的语句,可以用于数据复制  binary log

4、慢查询日志:记录所有执行时间超过long_query_time的所有查询或不使用索引的查询  slow log

 

默认情况下,所有日志创建于mysql数据目录中。通过刷新日志,可以强制mysql关闭和重新打开日志文件(或者在某些情况下切换到

一个新的日志)。当执行一个FLUSH LOGS语句或执行mysqladmin flush-logs 或mysqladmin refresh 时,将刷新日志

 

如果使用mysql复制功能,在复制服务器上可以维护更多日志文件,这种日志称为接替日志

 

其他日志功能会降低mysql数据库的性能。例如,在查询非常频繁的mysql数据库系统中,如果开启了通用查询日志和慢查询日志,

mysql数据库会花费很多时间记录日志。同时,日志会占用大量的磁盘空间

 


二进制日志

二进制日志就是我们经常说的binlog,主要记录mysql数据库的变化。

二进制日志以一种有效的格式,并且是事务安全的方式包含更新日志中可用的所有信息。

 

二进制日志包含关于每个更新数据库的语句的执行时间信息。他不包含没有修改任何数据的语句,例如select语句

使用二进制日志的最大目的是最大可能地恢复数据库,因为二进制日志包含备份后进行的所有更新

 

1、启动和设置二进制日志

默认情况下,二进制日志是关闭的,可以通过修改mysql的配置文件来启动和设置二进制日志

my.ini中[mysqld]组下面有几个设置是关于二进制日志的:

log-bin[=PATH/[FILENAME]]
expire_logs_days=10
max_binlog_size=100M

log-bin定义开启二进制日志;path表明日志文件所在的目录路径;

filename指定了日志文件的名称,如文件的全名是filename.0001,filename.0002等

除了上述文件之外,还有一个成为filename.index的文件,文件内容为所有日志的清单,可以使用记事本打开该文件

filename.index文件的内容,joe是我的计算机名,当前只有一个binlog文件:.\\joe-bin.000001

.\\joe-bin.000001

 

expire_logs_days定义了mysql清除过期日志的时间,即二进制日志自动删除的天数。

默认值为0,表示“没有自动删除”。当mysql启动或刷新二进制日志时可能删除该文件

 

max_binlog_size定义了单个文件的大小限制,如果二进制日志写入的内容大小超出给定值,日志就会发生滚动

(关闭当前文件,重新打开一个新的日志文件)。不能将该变量设置为大于1GB或小于4096字节。默认值是1GB

 

如果正在使用大事务 ,二进制日志文件大小还可能超过max_binlog_size的定义大小。

在my.ini配置文件中的[mysqld]组下,添加以下几个参数与参数值

[mysqld]
log-bin
expire_logs_days=10
max_binlog_size=100M

添加完毕之后,关闭并重启mysql服务进程,即可打开二进制日志,然后可以通过SHOW VARIABLES语句来查询日志设置

 

使用show VARIABLES  语句查看日志设置

show VARIABLES  LIKE ‘%log_%‘;

技术分享

 

可以看到log_bin为ON,max_binlog_size为104857600字节,换算为MB为100MB

MYSQL重新启动之后,就可以看到新产生的文件后缀为.000001和.index的两个文件,文件名称默认为主机名称

技术分享

如果想改变日志文件的目录位置,可以修改my.ini中log-bin参数

例如:

[mysqld]
log-bin="D:\\mysql\\log\\binlog"

关闭并重启mysql服务之后,新的二进制日志将出现在"D:\\mysql\\log\\binlog"路径下

 

提示:数据库文件最好不要和日志文件放在同一个磁盘上,这样当数据库文件所在磁盘发生损坏的时候,可以使用日志来恢复数据

 

2、查看二进制日志

mysql二进制日志是经常用到的。当mysql创建二进制日志文件时,首先创建一个以filename为名称,以index为后缀的文件;

再创建一个以filename为名称,以“.000001”为后缀的文件。当mysql服务重新启动一次,以“.000001”为后缀的文件会增加一个,

并且后缀名加1递增;如果日志长度超过了max_binlog_size的上限(默认是1GB)也会创建一个新的日志文件

 

show binary logs语句可以查看当前二进制日志文件个数和文件名。mysql二进制日志并不能直接查看,如果要查看日志内容,

可以通过mysqlbinlog命令查看

 

使用show binary logs语句查看二进制日志文件个数和文件名

SHOW BINARY LOGS;

技术分享

可以看到,当前有两个二进制日志文件,因为我把mysql服务重启了一次,日志文件的个数和mysql服务启动的次数相同。

每启动一次mysql服务,将会产生一个新的日志文件

 

使用mysqlbinlog查看二进制日志

mysqlbinlog是一个单独的exe,需要在命令行里执行我们把binlog文件里面的内容导出到binlog.txt

mysqlbinlog  "D:\\Program Files (x86)\\MySQL\\MySQL Server5.5\\data\\joe-bin.000002" >c:\\binlog.txt
技术分享
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#140731  7:49:30 server id 1  end_log_pos 107     Start: binlog v 4, server v 5.5.20-log created 140731  7:49:30 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG ‘
ioTZUw8BAAAAZwAAAGsAAAABAAQANS41LjIwLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAACKhNlTEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==
‘/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET [email protected]_COMPLETION_TYPE*/;
技术分享

 

3、删除二进制日志

mysql的二进制日志可以配置自动删除,同时mysql也提供了安全的手动删除二进制日志的方法

删除所有的二进制日志文件使用RESET MASTER;

RESET MASTER;

执行该语句,所有二进制日志将被删除,mysql 会重新创建二进制日志,新的日志文件扩展名将重新从000001开始编号

 

只删除部分二进制日志文件使用PURGE MASTER LOGS;

PURGE MASTER LOGS;

语法如下

PURGE {MASTER | BINARY} LOGS TO ‘log_name‘
PURGE {MASTER | BINARY} LOGS BEFORE ‘date‘

第一种方法指定文件名,执行该命令将删除文件名编号比指定文件名编号小的所有日志文件

第二种方法指定日期,执行该命令将删除指定日期以前的所有日志文件

 

 

使用PURGE MASTER LOGS;删除创建时间比binlog.000003早的所有日志文件

首先,为了演示语句操作过程,准备多个日志文件,读者可以对mysql服务进行多次重启

例如这里有10个日志文件

技术分享

执行删除命令

 PURGE MASTER LOGS TO "joe-bin.000003";

执行完成后,使用 show BINARY logs; 查看二进制日志

技术分享

可以看到joe-bin.000001和joe-bin.000002两个日志文件被删除了

 

使用 PURGE MASTER LOGS 删除2013年3月30日前创建的所有日志文件,执行命令如下

PURGE MASTER LOGS BEFORE ‘20130330‘

执行完毕之后,2013年3月30日前的日志文件都被删除,但2013年3月30日的日志会被保留

 

4、查看二进制日志里的操作记录

show binlog events;

比如想查看某一个二进制日志里面的记录,但又不想用mysqlbinlog,可以使用show binlog events

比如我想查看‘joe-bin.000006‘这个binlog文件的内容,执行如下命令

show binlog events in ‘joe-bin.000006‘;

内容如下

技术分享
Log_name: joe-bin.000006
Pos: 202 
Event_type: Query 
Server_id: 1 
End_log_pos: 304 
Info: use `test`; insert into bin(name) values (‘orange‘) 
技术分享

可以看到‘joe-bin.000006‘这个binlog文件记录了哪些SQL命令

 

如果想知道binlog文件的创建时间,就需要mysqlbinlog工具来查看

技术分享
C:\\ProgramData\\MySQL\\MySQL Server 5.5\\data>mysqlbinlog mysql_bin.000001 
/*!40019 SET @@session.max_insert_delayed_threads=0*/; 
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/; 
DELIMITER /*!*/; 
# at 4 
#131015 16:35:56 server id 1  end_log_pos 106   
技术分享

其中131015为日志创建时间,即2013年10月15日

 

5、使用二进制日志还原数据库

如果mysql服务器启用了二进制日志,在数据库出现意外丢失数据时,可以使用mysqlbinlog工具从指定的时间点开始

(例如,最后一次备份)直到现在,或另外一个指定的时间点的日志中恢复数据

 

要想从二进制日志恢复数据,需要知道当前二进制日志文件的路径和文件名。一般可以从配置文件(即my.cnf或者my.ini,文件名取决于mysql

服务器的操作系统)中找到路径

 

mysqlbinlog恢复数据的语法如下:

mysqlbinlog [option] filename |mysql -uuser -ppass

option是一些可选项,filename是日志文件名

比较重要的两对option参数是

--start-datetime、--stop-datetime

--start-position、--stop--position

--start-date、--stop-date可以指定恢复数据库的起始时间点和结束时间点

--start-position、--stop--position可以指定恢复数据的开始位置和结束位置

 

使用mysqlbinlog恢复mysql数据库到2014年7月2日15:27:48时的状态,执行下面命令

mysqlbinlog --stop-datetime="2014-7-2 15:27:48 " D:\\mysql\\log\\binlog\\binlog.000008 |mysql -u user -p password

该命令执行成功后,会根据binlog.000008日志文件恢复2014年7月2日15:27:48前的所有操作。

这种方法对误操作的删除数据比较有效

 

6、暂时停止二进制日志

如果在mysql的配置文件配置启动了二进制日志,mysql会一直记录二进制日志,修改配置文件,可以停止二进制日志,

但是需要重启mysql数据库。mysql提供了暂时停止二进制日志的功能。通过 SET SQL_LOG_BIN 语句可以使mysql暂停或者启动二进制日志

语法如下

SET sql_log_bin={0|1}

执行下面语句将暂停二进制日志

SET sql_log_bin=0;

执行下面语句将恢复记录二进制日志

SET sql_log_bin=1;

实际上,binlog文件有点类似于SQLSERVER的ldf文件,大家都保存了数据库的操作日志,都可以根据这个日志来恢复数据库

但是又有不同,mysql的binlog可用不开启,因为mysql的redo日志放在ib_logfile开头的文件里面,而undo日志跟数据文件是放在一起的

所以这一点跟SQLSERVER很不一样

 

在复制的时候,MYSQL一定要开启binlog功能,slave读取binlog,而SQLSERVER的订阅端读取发布端的ldf文件

所以刚才说:binlog文件有点类似于SQLSERVER的ldf文件


错误日志

错误日志文件包含了当mysqld启动和停止时,以及服务器在运行过程中发生任何严重错误时的相关信息。

在MYSQL中,错误日志也是非常重要的,mysql将启动和停止数据库信息以及一些错误信息记录到错误日志中

 

1、启动和设置错误日志

在默认情况下,错误日志会记录到数据库的数据目录下。如果没有在配置文件中指定文件名,则文件名默认为hostname.err。

例如:mysql所在服务器主机名为mysql-db,记录错误信息的文件名为mysql-db.err。如果执行了FLUSH LOGS,错误日志文件会重新加载

 

错误日志的启动和停止以及日志文件名,都可以通过修改my.ini(或者my.cnf)来配置。错误日志的配置项是log-error。

在[mysqld]下配置log-error,在启动错误日志。如果需要指定文件名,则配置项如下:

[mysqld]

log-error=[path/[file_name]]

path为日志文件所在的目录路径,filename为日志文件名。修改配置项后,需要重启mysql服务才生效

 

2、查看错误日志

通过错误日志可以监视系统的运行状态,便于及时发现故障,修复故障。mysql错误日志是以文本文件形式存储的,可以使用文本编辑器直接

查看mysql错误日志

 

如果不知道日志文件的存储路径,可以使用 show variables; 语句查看错误日志的存储路径。

语句如下

show variables LIKE ‘log_error‘;

技术分享

 

使用记事本查看mysql错误日志

通过上面 show variables LIKE ‘log_error‘; 的语句查看到错误日志的路径,然后用记事本打开该文件

我们可以看到错误日志内容如下

技术分享 View Code

 

3、删除错误日志

mysql的错误日志以文本文件的形式存储在文件系统中,可以直接删除

对于mysql5.5.7以前的版本,flush logs可以将错误日志文件重命名为filename.err_old,

并创建新的日志文件。但是从mysql5.5.7开始,flush logs只是重新打开日志文件,并不做日志备份和创建的操作。

如果日志文件不存在,mysql启动或者执行flush logs时会创建新的日志文件

 

在运行状态下删除错误日志文件后,mysql并不会自动创建日志文件。flush logs在重新加载日志的时候,如果文件不存在,

则会自动创建。所以在删除错误日志之后,如果需要重建日志文件需要在服务器端执行以下命令:

mysqladmin -u root -p flush-logs

或者在客户端登录mysql数据库,执行flush logs语句

flush logs;

 

删除err文件,并用flush logs语句重建log-error文件

手动删除文件

技术分享

手动执行 flush logs; ,err文件恢复了

技术分享

 打开err文件,里面什么都没有

技术分享


通用查询日志

 

通用查询日志记录了mysql的所有用户操作,包括启动和关闭服务、执行查询和更新语句等

 

1、启动和设置通用查询日志

mysql服务器默认情况下并没有开启通用查询日志。如果需要通用查询日志,可以通过修改my.ini或my.cnf配置文件来

开启。在my.ini或my.cnf的[mysqld]组下加入log选项

形式如下

[mysqld]

log[=path/[filename]]

path为日志文件所在目录路径,filename为日志文件名。如果不指定目录和文件名,通用查询日志将默认存储在mysql数据目录中的

hostname.log文件中。hostname是mysql数据库的主机名

这里在[mysqld]下面增加选项log,后面不指定参数值

[mysqld]
log

 

2、查看通用查询日志

通用查询日志中记录了用的所有操作。通过查看通用查询日志,可以了解用户对mysql进行的操作。通用查询日志是

以文本文件形式存储在文件系统中的,可以使用文本编辑器直接打开通用日志文件进行查看,Windows下可以使用记事本

Linux下可以使用vim、gedit等

使用记事本查看mysql通用查询日志

技术分享

文件内容如下

技术分享
E:\\Program Files\\MySQL\\MySQL Server 5.5\\bin\\mysqld, Version: 5.5.19-log (MySQL Community Server (GPL)). started with:
TCP Port: 3306, Named Pipe: (null)
Time                 Id Command    Argument
140801 23:39:33        1 Connect    [email protected] on 
            1 Query    SHOW VARIABLES
            1 Query    SHOW WARNINGS
            1 Query    select timediff( curtime(), utc_time() )
            1 Query    SHOW COLLATION
            1 Query    SET NAMES utf8
            1 Query    SET character_set_results=NULL
            1 Query    SELECT * FROM `emp`
140801 23:39:44        1 Query    SELECT * FROM `emp`
            1 Query    SELECT * FROM `emp`
140801 23:39:55        1 Query    USE test;

SELECT * FROM `emp`
            1 Init DB    test
技术分享

可以看到mysql启动信息和用户root连接服务器与执行查询语句的记录

 

3、删除通用查询日志

通用查询日志是以文本文件的形式存储在文件系统中的。通用查询日志记录用户的所有操作

因此在用户查询、更新频繁的情况下,通用查询日志会增长得很快。DBA可以定期删除比较早的通用日志,以节省磁盘空间

 

可以用直接删除日志文件的方式删除通用查询日志。要重新建立新的日志文件,可使用语句

mysqladmin -flush logs

直接删除log文件

技术分享

执行 flush logs 

技术分享

 

 log文件重新生成了

技术分享


慢查询日志

 

慢查询日志是记录查询时长超过指定时间的日。慢查询日志主要用来记录执行时间较长的查询语句

通过慢查询日志,可以找出执行时间较长、执行效率较低的语句,然后进行优化

 

1、启动和设置慢查询日志

mysql中慢查询日志默认是关闭的,可以通过配置文件my.ini或my.cnf中的log-slow-queries选项打开,也可以在mysql服务

启动的时候使用--log--slow-queries[=file_name]启动慢查询日志。启动慢查询日志时,需要在my.ini或者my.cnf文件中

配置long_query_time选项指定记录阀值,如果某条查询语句的查询时间超过了这个值,这个查询过程将被记录到慢查询日志

文件中。

 

在my.ini或者my.cnf文件中开启慢查询日志的配置如下:

[mysqld]

log-slow-queries[=path/[filename]]
long_query_time=n

path为日志文件所在目录路径,filename为日志文件名。如果不指定目录和文件名称,默认存储在数据目录中

文件名为hostname-slow.log,hostname是mysql服务器的主机名。参数n是时间值,单位是秒。

如果没有设置long-query_time选项,默认时间为10秒

 

开启慢查询日志

[mysqld]
log-slow-queries
long_query_time=1

 

2、查看慢查询日志

mysql的慢查询日志是以文本形式存储的,可以直接使用文本编辑器查看。在慢查询日志中,记录着执行时间较长的查询语句,

用户可以从慢查询日志中获取执行效率较低的查询语句,为查询优化提供重要的依据

 

查看慢查询日志的一些参数

show variables like ‘%slow%‘;

技术分享

 

查看慢查询日志文件里的内容,使用文本编辑器打开数据目录下的WIN7U-20130414Z-slow.log文件

技术分享

技术分享
E:\\Program Files\\MySQL\\MySQL Server 5.5\\bin\\mysqld, Version: 5.5.19-log (MySQL Community Server (GPL)). started with:
TCP Port: 3306, Named Pipe: (null)
Time                 Id Command    Argument
# Time: 140802  0:02:29
# [email protected]: root[root] @ localhost [::1]
# Query_time: 7.578125  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 0
use test;
SET timestamp=1406908949;
SELECT BENCHMARK (10000000,PASSWORD (‘newpwd‘));
技术分享

可以看到这里记录了一条慢查询日志。执行该条语句的帐户是root @ localhost 

查询时间是Query_time: 7.578125秒

查询语句是 SELECT BENCHMARK (10000000,PASSWORD (‘newpwd‘)); 

该语句查询时间大大超过了设置值1秒,因此被记录在慢查询日志文件中

BENCHMARK函数简介:http://database.51cto.com/art/201010/229366.htm 

 

3、删除慢查询日志

和通用查询日志一样,慢查询日志也可以直接删除。删除后在不重启服务器的情况下,需要执行

mysqladmin -u root -p flush logs

重新生成日志文件,或者在客户端登录到服务器执行 flush logs; 语句重建日志文件

 

官方mysql的慢查询日志在这里有一个缺陷,就是查询阀值只能是1秒或以上,如果要设置一秒以下就无能为力了

这时候如果想找出1秒以下的慢查询SQL,可以使用percona提供的microslow-patch来突破限制,将慢查询时间阀值减小到毫秒级别


平时应打开哪些日志

日志既会影响mysql的性能,又会占用大量磁盘空间。因此,如果不必要,应尽可能少地开启日志。

根据不同的使用环境,考虑开启不同的日志。

例如开发环境中优化查询效率低的语句,可以开启慢查询日志,或者生产环境中发现某些SQL执行特别慢也可以开启

如果磁盘空间不是特充足可以在高峰期间开启,在捕获到查询慢的SQL之后再关闭慢查询日志

 

如果需要搭建复制环境,那么就一定要开启二进制日志,如果数据特别重要也建议开启二进制日志,以便数据库损坏的时候也可以通过二进制日志

挽救一部分数据

 

通用日志无论在哪种情况下,一般不建议开启 


总结

本文简单的阐述了MYSQL的日志面的内容,MYSQL的日志系统还是比较完善的,希望这篇文章对大家有帮助

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

2014-11-27补充 写事务日志流程

技术分享

以上是关于MySQL学习日志十五,规范化数据库设计的主要内容,如果未能解决你的问题,请参考以下文章

MySQL学习笔记(十五)——索引的创建和设计原则

Python学习日记(三十五) Mysql数据库篇 三

Mysql学习总结(16)——Mysql之数据库设计规范

MySQL命名设计及使用规范--------来自标点符的《MySQL命名设计及使用规范》

学习四十五

Java基础学习笔记二十五 MySQL