去IOE
去IBM(小型机)、Oracle(数据库)、EMC(存储)
一套就几百万、上千万。
互联网企业硬件架构描述,主要是存储架构:
pc server:
本地只有2块盘,做raid1,主要是用来做OS,放mysql软件的;
如果本地盘IO高的话(正常是很低的,因为本地盘只装软件啊):
1.产生了严重的swap(缓页);
2.数据文件建到本地盘了。
原理是啥呢:
当互联网公司有钱了,一般都会去购买PCIE闪卡,有3T(5万一个)和6T(10万一个)的。直接插到服务器的主板上。这样,本地的两个盘就能识别它的空间。而闪卡的IOPS能够达到50万(正常的盘在100左右…)。
mysql> show variables like '%base%'; #查看数据库装在哪里了
mysql> show variables like '%data%'; #查看数据库的数据文件存在哪里
MySQL数据库的文件:
数据库启动的时候,读取的第一个文件
默认在/etc/my.cnf
# mysql --help | grep my.cnf
/etc/my.cnf、/etc/mysql/my.cnf、/usr/etc/my.cnf、~/.my.cnf
mysql启动的时候,先找/etc/my.cnf配置文件,找不到,就找/etc/mysql/my.cnf,找到找不到都会找一遍。
所以,一般在启动mysql的时候,都手动指定参数文件:
# mysqld_safe --defaults-file=/etc/my.cnf &
①Oracle实例启动时,若找不到参数文件,是不能进行装载(mount)操作的。
②MySQL实例可以不需要参数文件,这时所有的参数值取决于编译MySQL时指定的默认值和源代码中指定参数的默认值。
但是,mysql如果在默认的数据库目录下找不到mysql架构,则启动会失败。可以在错误日志中找到如下内容:
注意:修改参数时,一定要先看官方文档!了解参数是否动态,允许的值和范围等。
mysql>show variables like '%data%'; #看数据目录在哪
可以看到,数据文件目录/var/lib/mysql/下面的权限:
目录权限一般是700,属主和属组都是mysql
文件权限一般是660,属主和属组都是mysql
log buffer往log file里写redo log的触发机制:
当后台脏页往磁盘里写的时候,要先把日志写过来。–》WAL【日志先写】
【WAL:】
【磁盘上的数据是比较旧的,而日志文件是比较新的。】
【日志比最新的数据还要新】
数据库崩了之后,先要做前滚(redo log+旧的数据块),再做回滚(undo、rollback) –》保护脏页。
用户线程连接数据库,进行dml操作,操作数据块,产生redo log(记录的是:对哪个数据文件space no、哪个数据页page no、哪个数据行row no、做的什么dml、value)
【不管事务;只盯着脏页;按照时间顺序记录】
每个用户线程连上来后,工作空间里已讲的有:
sort_buffer_size(排序空间)、binlog_buffer_size…..
工作原理:假设事务里面有5条sql语句,commit的时候,binlog_buffer才会写回到磁盘的binlog。binlog不会被覆盖,是一直存在的。
binlog的特点:
mysql> show master status \G #查看bin log的状态。
通过配置参数 log-bin[=name ] 可以启动二进制日志 。如果不指定name ,则默认二进制日志文件名为主机名,后缀名为二进制日志的序列号,所在路径为数据库数据所在目录 (datadir ) ,如 :
【注意!!修改配置文件后,要先停止服务,再启动服务!!
①# mysqladmin -uroot -p shutdown -h127.0.0.1 -P3307
②#mysqld_safe --defaults-file=/etc/mysqla.cnf &
③# mysql -uroot -p -P3307 -h127.0.0.1
该参数指定了单个二进制日志文件的最大值,如果超过该值,则产生新的二进制日志文件,后缀名+1,并记录到 .index 文件 。从MySQL5.0开始的默认值为 1 073 741 824 ,代表1GB(之前的版本max-binlog-size默认大小为1.1GB)
默认32K。cache写不下了,就会往磁盘写。
当使用事务的表存储引擎 ( 如InnoDB存储引擎) 时,所有未提交 ( uncommitted )的二进制日志会被记录到一个缓存中 ,等该事务提交时 ( committed ) 时直接将缓冲中的二进制日志写入二进制日志文件,而该缓冲的大小由 binlog_cache_size 决定,默认大小为 32KB 。此外 ,binlog_cache_size 是基于会话 ( session ) 的,也就是说 ,当一个线程开始一个事务时 ,MySQL会自动分配一个大小为 binlog_cache_size 的缓存 ,因此该值的设置需要 相当小心,不能设置过大 。当一个事务的记录大于设定的 binlog_cache_size 时,MySQL会把缓冲中的日志写入一个临时文件中 ,因此该值又不能设得太小 。通过SHOW GLOBAL STATUS命令查看 binlog_cache_use 、binlog_cache_disk_use 的状态 ,可以判断当前 binlog_cache_size 的设置是否合适。Binlog_cache_use 记录了使用缓冲写二进制日志的次数, binlog_cache_disk_use 记录了使用临时文件写二进制日志的次数 。现在来看一个数据库的状态 :
mysql> show variables like '%binlog_cache_size%';
mysql> show global status like '%binlog_cache%';
所以,一般当使用缓冲的次数很大很大,临时文件的使用次数也很大很大时,才有必要调整binlog_cache_size的值。
同步二进制文件。一般设为1–》绕过文件系统的缓存。
默认情况下,二进制日志并不是在每次写的时候同步到磁盘 (我们可以理解为缓冲写)。因此,当数据库所在操作系统发生宕机时 ,可能会有最后一部分数据没有写入二进制日志文件中 。这会给恢复和复制带来问题 。参数sync_binlog=[ N]表示每写缓冲多少次就同步到磁盘。如果将N设为 1,即 sync_binlog= 1表示采用同步写磁盘的方式来写二进制日志 ,这时写操作不使用操作系统 的缓冲来写二进制日志。该默认值为0 ,如果使用InnoDB存储引擎进行复制,并且想得到最大的高可用性,建议将该值设为ON。不过该值为ON时,确实会对数据库的IO系统带来一定的影响。
但是 ,即使将sync_binlog 设为 1,还是会有一种情况会导致问题的发生 。当使用 lnnoDB存储引擎时,在一个事务发出COMMIT动作之前 ,由于sync_binlog设为1,因此会将二进制日志立即写入磁盘 。如果这时已经写入了二进制日志,但是提交还没有发生 ,并且此时发生了宕机 ,那么在MySQL数据库下次启动时 ,因为COMMIT操作井没有发生,所以这个事务会被回滚掉。但是二进制日志已经记录了该事务信息,不能被回滚。这个问题可以通过将参数innodb_support_xa 设为1来解决,虽然innodb_support_xa 与XA事务有关,但它同时也确保了二进制日志和InnoDB存储引擎数据文件的同步。
两个参数表示需要写入或者忽略写入哪些库的日志。默认为空,表示需要将所有库的日志同步到二进制日志。
如果当前数据库是复制中的slave角色 ,则它不会将从master取得并执行的二进制日志写入自己的二进制日志文件中。如果需要写入,则需要设置log-slave-update。如果需要搭建master=>slave=>slave 架构的复制,则必须设置该参数。
binlog_format参数十分重要,这影响了记录二进制日志的格式。在MySQL 5.1版本之前,没有这个参数。所有二进制文件的格式都是基于SQL语句 ( statement ) 级别的,因此基于这个格式的二进制日志文件的复制 (Replication ) 和Oracle逻辑Standby有点相似。同时,对于复制是有一定要求的如rand 、uuid 等函数 ,或者有使用触发器等可能会导致主从服务器上表的数据不一致( not sync),这可能使得复制变得没有意义。另一个影响是,会发现InnoDB存储引擎的默认事务隔离级别是REPEATABLE READ。这其实也是因为二进制日志文件格式的关系 ,如果使用READ COMMITTED的事务隔离级别(大多数数据库 如Oracle 、Microsoft SQL Server数据库的默认隔离级别) 会出现类似丢失更新的现象,从而出现主从数据库上的数据不一致。
四个级别与四种现象的关系是:
英文 | 更新丢失 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|
Read Uncommited 读未提交 | 不会出现 | 会出现 | 会出现 | 会出现 |
Read Commited 读已提交 | 不会出现 | 不会出现 | 会出现 | 会出现 |
Repeatable Read 可重复读 | 不会出现 | 不会出现 | 不会出现 | 会出现 |
Serializable 串行化 | 不会出现 | 不会出现 | 不会出现 | 不会出现 |
MySQL 5.1开始引入了binlog_format 参数 ,该参数可设的值有STATEMENT(语句模式)、ROW(行模式)和MIXED(混合模式) 。
此外 ,binlog_format 参数还有对于存储引擎的限制 ,如表3-1所示。
binlog_format 是动态参数 ,因此可以在数据库运行环境下进行更改,我们可以将当前会话的binlog_format 设为ROW ,如 :
mysql>set @@session.binlog_format='ROW';
#修改
mysql>select @@session.binlog_format;
#查看binlog_format的状态
mysql>show master status\G
#查看binlog文件的情况 --》可以计算binlog二进制日志的生成速度(差值/间隔)
二进制日志文件的文件格式为二进制(好像有点废话),不能像错误日志文件,慢查询日志文件用cat、head、tail等命令来查看 。想要查看二进制日志文件的内容,须通过 MySQL提供的工具 mysqlbinlog。
#mysqlbinlog -vv mysqlserver.000003
【注意!只有编译安装的mysql实例,才能开启binlog功能!!】
【加个vv再显示就好了】
PS:UUID
【看到,到了从库以后,跟在主库看到的是不一样的!!】
所以,用row模式可以记录dml时具体的产生的数记录下来。
DBA:日志查看能力才是核心的能力。
错误日志文件对MySQL的启动、运行 、关闭过程进行了记录。MySQL DBA在遇到问题时应该首先查看该文件。该文件不但记录了出错信息 ,也记录一些警告信息或者正确的 信息 。总的来说,这个文件更类似于 Oracle的alert文件 ,只不过在默认情况下是 err结尾。你可以通过 show variables like ‘log_error’ ,来定位该文件,如:
看日志的技巧:
①ll -t,看时间最新的;
②看大小最大的。一般越大的包含的核心内容越多。
#cd /var/log/
#ll
mysqld.log –>数据库系统最重要的错误日志;
messages –>linux最重要的日志。
前面提到可以通过错误日志得到一些关于数据库优化的信息帮助,而慢查询能为 SQL语句的优化带来很好的帮助 。可以设一个阈值,将运行时间超过该值的所有SQL语句都记录到慢查询日志文件中。该阈值可以通过参数 long_query_time 来设置,默认值为10 , 代表10秒。
默认情况下 ,MySQL数据库并不启动慢查询日志 ,你需要手工将这个参数设为 ON , 然后启动,可以看到如下结果 :
mysql> show variables like '%slow%';
mysql> show variables like '%long%';
这里需要注意两点 。首先,设置long_query _time这个阑值后 ,MySQL数据库会记录运行时间超过该值的所有SQL语句,但对于运行时间正好等于 long_query_time 的情况,并不会被记录下 。也就是说 ,在源代码里是判断大于 long_query_time,而非大于等于 。其次 从MySQL 5.1开始 ,long_query _time开始以 微秒 记录SQL语句运行时间 ,之前仅用秒为单 位记录。这样可以更精确地记录SQL的运行时间,供DBA分析。对DBA来说,一条SQL语 句运行0.5秒和0.05秒是非常不同的 ,前者可能已经进行了表扫 ,后面可能是走了索引。
重点:Row_sent: Row_examined比值==1:20 就不快了。【两个值越近越好】
【如果一个sql执行的慢,是因为锁,那就没法调优了。】
慢查询的原因一般是:
另一个和慢查询日志有关的参数是 log_queries_not_using_indexes,如果运行的SQL语句没有使用索引,则MySQL数据库同样会将这条 SQL语句记录到慢查询日志文件。首先 确认打开了log_queries_not_using_indexes:
mysql> show variables like '%log_queries_not_using_indexes%';
#查看是否打开了该功能
当为OFF时,表示它使用了索引,即使是慢查询,也不会记录到慢查询文件。
最经典的就是看它的执行计划:explain
mysql>explain select * from customer where c_street_1 like '%abc%';
possible_keys==NULL:表示这个表没有做索引,走的全表扫描;
MySQL5.6.5版本开始新增了一个参数 log_throttle_queries_not_using_indexes,用来表示每分钟允许记录到slow log的且未使用索引的SQL语句次数,该值默认为0,表示没有限制(不好)。在生产环境下,若没有使用索引,此类SQL语句会疯狂地被记录到slow log,从而导致slow log文件的大小不断增加,故DBA可通过此参数进行配置。
我们可以通过慢查询日志来找出有问题的SQL语句,对其进行优化。随着MySQL数据库服务器运行时间的增加,可能会有越来越多的 SQL查询被记录到了慢查询日志文件中,这时要分析该文件就显得不是很容易了。MySQL这时提供的 mysqldumpslow 命令,可以很好地解决这个问题:
#mysqldumpslow nh122-190-slow.log
--verbose verbose
--debug debug
--help write this text to standard output
-v verbose
-d debug
-s ORDER what to sort by (al,at,ar,c,l,r,t),'at' is default
al: average lock time
ar: average rows sent
at: average query time
c : count
l : lock time
r : rows sent
t : query time
-r reverse the sort order ( largest last instead of f irst )
-t NUM just show the top n queries
-a don't abst ract all numbers to N and strings to ’ S
-n NUM abstract numbers with at least n digits within names
-g PATTERN grep : only consider stmts that include this string
-h HOSTNAME hostname of db server for *-slow.log filename (can be wildcard),default is '*',i.e.match all
-i NAME name of server instance (if using mysql.server startup script)
-l don't subtract lock time f rom total time
比如,我们想得到锁定时间最长的10条SQL语句,可以运行:
#/usr/local/mysql/bin/mysqldumpslow -s al -n 10 david.log
参数log_output 指定了慢查询输出的格式,默认为FILE ,你可以将它设为TABLE , 后就可以查询mysql架构下的slow_log表了 ,如:
mysql> show variables like '%log_output%';
参数log_output是动态的 ,并且是全局的。我们可以在线进行修改
慢查询的缺点:
查询日志记录了所有对 MySQL数据库请求的信息,不论这些请求是否得到了正确的执 行。默认文件名为 :主机名.log
mysql> show variables like ‘%general%’;
看到,此时查询日志是OFF关闭的。查询日志文件是/var/lib/mysql/liupeng.log
mysql> set @@global.general_log=on;
可以用作数据库的安全审计,看你干了什么坏事。
查询日志不要打开。
因为记录的范围太大,虽然安全了,但是对性能有很大的拉低。
Unix 系统下本地连接MySQL可以采用Unix域套接字方式 ,这种方式需要一个套接字 ( socke ) 文件 。
mysql> show variables like '%socket%';
【有多套数据库实例的时候这样连接】
【连哪个数据库,就连哪个数据库的sock文件】
#mysql -S /mysqldata/mysql.sock -uroot -p123123
当MySQL 实例启动时,会将自己的进程 ID写入一个文件中一一该文件即为pid文件。该文件可由参数 pid_file 控制。默认路径位于数据库目录下,文件名为主机名.pid 。
mysql> show variables like ‘%pid_file%’;
因为MySQL插件式存储引擎的体系结构的关系,MySQL对于数据的存储是按照表的 ,所以每个表都会有与之对应的文件( 对比SQL Server是按照每个数据库下的所有表或索引都存在mdf文件中)。不论采用何种存储引擎,MySQL都有一个以frm为后缀名的文件,这个文件记录了该表的表结构定义。
frm还用来存放视图的定义,如我们创建了一个 v_a 视图 ,那么对应地会产生一个 v_a.frm 文件,用来记录视图的定义,该文件是文本文件,可以直接使用 cat 命令进行查看。
ibd文件和frm文件的区别:
#strings XX.frm --》可以看.frm对应的表的结构信息。
共享表空间:
adaptive hash index;
insert buffer;造成它暴增的原因 –》①索引多②索引的顺序跟表的顺序差别很大
double write; –》很小
undo。–》最不可控,可能会变成很大。
将undo从ibdata里面独立出来,初始化数据库的时候,时候就不能改变了。
大事务、长事务一般会导致undo暴增。
之前介绍的文件都是MySQL数据库本身的文件,和存储引擎无关 。除了这些文件外,每个表存储引擎还有其自己独有的文件。和InnoDB存储引擎密切相关的文件,这些文件包括重做日志文件 、表空间文件。
InnoDB存储引擎在存储设计上模仿了 Oracle ,将存储的数据按表空间进行存放 。默认配置下,会有一个初始化大小为 10MB 、名为ibdata1 的文件。该文件就是默认的表空间文件(tablespace file)。可以通过参数innodb_data_file_path 对其进行设置 。格式如下 :
innodb_data_file_path=datafile_spec1[ ;datafile_spec2] ……
也可以用多个文件组成一个表空间 ,同时制定文件的属性 ,如:
[ mysqld ]
innodb_data_file_path = /db /ibdata1:2000M; /dr2/db/ibdata2:2000M:autoextend
这里将/db/ibdata1 和/dr2/db/ibdata2 两个文件用来组成表空间 。若这两个文件位于不同的磁盘上 ,则可以对性能带来一定程度的提升 。两个文件的文件名后都跟了属性,表示文件idbdata1 的大小为2000MB,文件ibdata2的大小为2000MB,但是如果用满了这 2000MB 后 该文件可以自动增长 ( autoextend )。
设置 innodb_data_file_path 参数后 ,之后对于所有基于 lnnoDB存储引擎的表的数据都会记录到该文件内 。而通过设置参数 innodb_file_per_table,我们可以将每个基于 InnoDB 存储引擎的表单独产生一个表空间 ,文件名为表名 .ibd ,这样不用将所有数据都存放于默认的表空间中。下面这台服务器设置了innodb_file_per_table ,可以看到 :
表Profile 、t1、t2都是lnnoDB 的存储引擎 ,由于设置参数innodb_file_per_table=ON ,因此产生了单独的.ibd表空间文件 。需要注意的是,这些单独的表空间文件仅存储该表的数据、索引和插入缓冲等信息 ,其余信息还是存放在默认的表空间中 。图3-1 显示了InnoDB存储引擎对于文件的存储方式:
默认情况下会有两个文件,名称分别为 ib_logfile0和ib_logfile1 。MySQL 官方手册中将其称为InnoDB存储引擎的日志文件,不过更准确的定义应该是重做日志文件(redo log file)。为什么强调是重做日志文件呢?因为重做日志文件对于InnoDB存储引擎至关重要,它们记录了对于InnoDB存储引擎的事务日志。
重做日志文件的主要目的是,万一实例或者介质失败(media failure),重做日志文件就能派上用场。如数据库由于所在主机掉电导致实例失败,InnoDB 存储引擎会使用重做日志恢复到掉电前的时刻,以此来保证数据的完整性。
每个InnoDB存储引擎至少有 1个重做日志文件组(group),每个文件组下至少有 2个重做日志文件,如默认的ib_logfile0 、ib_logfile 1 。为了得到更高的可靠性,你可以设置多个镜像日志组 (mirrored log groups),将不同的文件组放在不同的磁盘上。日志组中每个重做日志文件的大小一致 ,并以循环方式使用。InnoDB存储引擎先写重做日志文件1,当达到文件的最后时,会切换至重做日志文件 2 ,当重做日志文件 2也被写满时 ,会再切换到重做日志1中。
参数innodb_log_file_size 、innodb_log_files_in_group 、innodb_mirrored_log_groups、innodb_log_group_home_dir影响着重做日志文件的属性:
重做日志文件的大小设置对于MySQL数据库各方面还是有影响的。一方面不能设置得太大,如果设置得很大,在恢复时可能需要很长的时间;另一方面又不能太小了,否则可能导致一个事务的日志需要多次切换重做日志文件。
redo log file:不能太大,不能太小!
首先,二进制日志会记录所有与 MySQL有关的日志记录 ,包括InnoDB 、My ISAM 、Heap等其他存储引擎的日志 。而InnoDB 存储引擎的重做日志只记录有关其本身的事务日志 。其次,记录的内容不同,不管你将二进制日志文件记录的格式设为 STATEMENT还是ROW ,又或者是MIXED ,其记录的都是关于一个事务的具体操作内容 。而InnoDB存储引擎的重做日志文件记录的关于每个页 ( Page ) 的更改的物理情况 。此外,写入的时间也不同 ,二进制日志文件是在事务提交前进行记录的,而在事务进行的过程中,不断有重做日志条目 ( redo entry ) 被写入重做日志文件中 。
对于写入重做日志文件的操作不是直接写 ,而是先写入一个重做日志缓冲 ( redo log buffer ) 中,然后根据按照一定的条件写入日志文件 。图3-3很好地 表示了这个过程 。
从日志缓冲写入磁盘上的重做日志文件是按一定条件的 ,那这些条件有哪些呢?
主线程 ( master thread ) ,知道在主线程中每秒会将重做日志缓冲写入磁盘的重做日志文件中,不论事务是否已经提交 。另一个触发这个过程是由参数 innodb_ flush_log_at_trx_commit 控制 ,表示在提交(commit)操作时,处理重做日志的方式。
参数innodb_flush_log_at_trx_commit 可设的值有0 、1、2。