1、MySQL的复制原理以及流程
(1)复制基本原理流程
1. 主:binlog线程——记录下全部改变了数据库数据的语句,放进master上的binlog中;
2. 从:io线程——在使用start slave 以后,负责从master上拉取 binlog 内容,放进 本身的relay log中;
3. 从:sql执行线程——执行relay log中的语句;
(2)MySQL复制的线程有几个及之间的关联
MySQL 的复制是基于以下 3 个线程的交互( 多线程复制里面应该是 4 类线程):
1. Master 上面的 binlog dump 线程,该线程负责将 master 的 binlog event 传到slave;
2. Slave 上面的 IO 线程,该线程负责接收 Master 传过来的 binlog,并写入 relay log;
3. Slave 上面的 SQL 线程,该线程负责读取 relay log 并执行;
4. 若是是多线程复制,不管是 5.6 库级别的假多线程仍是 MariaDB 或者 5.7 的真正的多线程复制, SQL 线程只作 coordinator,只负责把 relay log 中的 binlog读出来而后交给 worker 线程, woker 线程负责具体 binlog event 的执行;
(3)MySQL如何保证复制过程当中数据一致性及减小数据同步延时
1.在 MySQL5.5 以及以前, slave 的 SQL 线程执行的 relay log 的位置只能保存在文件( relay-log.info)里面,而且该文件默认每执行 10000 次事务作一次同步到磁盘, 这意味着 slave 意外 crash 重启时, SQL 线程执行到的位置和数据库的数据是不一致的,将致使复制报错,若是不重搭复制,则有可能会致使数据不一致。MySQL 5.6 引入参数 relay_log_info_repository,将该参数设置为 TABLE 时, MySQL 将 SQL 线程执行到的位置存到mysql.slave_relay_log_info 表,这样更新该表的位置和 SQL 线程执行的用户事务绑定成一个事务,这样 slave 意外宕机后, slave 经过 innodb 的崩溃恢复能够把 SQL 线程执行到的位置和用户事务恢复到一致性的状态。
2. MySQL 5.6 引入 GTID 复制,每一个 GTID 对应的事务在每一个实例上面最多执行一次, 这极大地提升了复制的数据一致性;
3. MySQL 5.5 引入半同步复制, 用户安装半同步复制插件而且开启参数后,设置超时时间,可保证在超时时间内若是 binlog 不传到 slave 上面,那么用户提交事务时不会返回,直到超时后切成异步复制,可是若是切成异步以前用户线程提交时在 master 上面等待的时候,事务已经提交,该事务对 master上面的其余 session 是可见的,若是这时 master 宕机,那么到 slave 上面该事务又不可见了,该问题直到 5.7 才解决;
4. MySQL 5.7 引入无损半同步复制,引入参 rpl_semi_sync_master_wait_point,该参数默认为 after_sync,指的是在切成半同步以前,事务不提交,而是接收到 slave 的 ACK 确认以后才提交该事务,今后,复制真正能够作到无损的了。
5.能够再说一下 5.7 的无损复制状况下, master 意外宕机,重启后发现有 binlog没传到 slave 上面,这部分 binlog 怎么办???分 2 种状况讨论, 1 宕机时已经切成异步了, 2 是宕机时还没切成异步???这个怎么判断宕机时有没有切成异步呢???分别怎么处理???
5.5 是单线程复制, 5.6 是多库复制(对于单库或者单表的并发操做是没用的), 5.7 是真正意义的多线程复制,它的原理是基于 group commit, 只要master 上面的事务是 group commit 的,那 slave 上面也能够经过多个 worker线程去并发执行。和 MairaDB10.0.0.5 引入多线程复制的原理基本同样。
(4)工做遇到的复制 bug 的解决方法
5.6 的多库复制有时候本身会中止,咱们写了一个脚本从新 start slave;待补充…
2、MySQL中myisam与innodb的区别,至少5点
(1)问5点不一样
1.InnoDB支持事物,而MyISAM不支持事物
2.InnoDB支持行级锁,而MyISAM支持表级锁
3.InnoDB支持MVCC, 而MyISAM不支持
5.InnoDB不支持全文索引,而MyISAM支持。
6.InnoDB不能经过直接拷贝表文件的方法拷贝表到另一台机器, myisam 支持
7.InnoDB表支持多种行格式, myisam 不支持
8.InnoDB是索引组织表, myisam 是堆表
(3)各类不一样 mysql 版本的Innodb的改进
MySQL5.6 下 Innodb 引擎的主要改进:
3.transportable tablespace( alter table discard/import tablespace)
4.MySQL 正常关闭时,能够 dump 出 buffer pool 的( space, page_no),重启时 reload,加快预热速度
5.索引和表的统计信息持久化到 mysql.innodb_table_stats 和mysql.innodb_index_stats,可提供稳定的执行计划
6.Compressed row format 支持压缩表
1.修改 varchar 字段长度有时可使用 online DDL
4.支持新建 innodb tablespace,并能够在其中建立多张表
5.磁盘临时表采用 innodb 存储,而且存储在 innodb temp tablespace 里面,之前是 myisam 存储
(4)2者select count(*)哪一个更快,为何
myisam更快,由于myisam内部维护了一个计数器,能够直接调取。
(5)2 者的索引的实现方式
都是 B+树索引, Innodb 是索引组织表, myisam 是堆表, 索引组织表和堆表的区别要熟悉
3、MySQL中varchar与char的区别以及varchar(50)中的50表明的涵义
(1)varchar与char的区别
在单字节字符集下, char(N) 在内部存储的时候老是定长, 并且没有变长字段长度列表中。在多字节字符集下面, char(N)若是存储的字节数超过 N,那么 char(N)将和 varchar(N)没有区别。在多字节字符集下面,若是存储的字节数少于 N,那么存储 N 个字节,后面补空格,补到 N 字节长度。都存储变长的数据和变长字段长度列表。varchar(N)不管是什么字节字符集,都是变长的,即都存储变长数据和变长字段长度列表
(2)varchar(50)中50的涵义
最多存放50个字符,varchar(50)和(200)存储hello所占空间同样,但后者在排序时会消耗更多内存,由于order by col采用fixed_length计算col长度(memory引擎也同样)。在早期 MySQL 版本中, 50 表明字节数,如今表明字符数。
(3)int(20)中20的涵义
不影响内部存储,只是影响带 zerofill 定义的 int 时,前面补多少个 0,易于报表展现
(4)mysql为何这么设计
对大多数应用没有意义,只是规定一些工具用来显示字符的个数;int(1)和int(20)存储和计算均同样;
4、innodb的事务与日志的实现方式
(1)有多少种日志
(2)日志的存放形式
redo:在页修改的时候,先写到 redo log buffer 里面, 而后写到 redo log 的文件系统缓存里面(fwrite),而后再同步到磁盘文件( fsync)。
Undo:在 MySQL5.5 以前, undo 只能存放在 ibdata*文件里面, 5.6 以后,能够经过设置 innodb_undo_tablespaces 参数把 undo log 存放在 ibdata*以外。
(3)事务是如何经过日志来实现的,说得越深刻越好
由于事务在修改页时,要先记 undo,在记 undo 以前要记 undo 的 redo, 而后修改数据页,再记数据页修改的 redo。Redo(里面包括 undo 的修改) 必定要比数据页先持久化到磁盘。当事务须要回滚时,由于有 undo,能够把数据页回滚到前镜像的
状态,崩溃恢复时,若是 redo log 中事务没有对应的 commit 记录,那么须要用 undo把该事务的修改回滚到事务开始以前。若是有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。
5、MySQL binlog的几种日志录入格式以及区别
(1) 各类日志格式的涵义
1.Statement:每一条会修改数据的sql都会记录在binlog中。
优势:不须要记录每一行的变化,减小了binlog日志量,节约了IO,提升性能。(相比row能节约多少性能 与日志量,这个取决于应用的SQL状况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,
可是考虑到若是带条 件的update操做,以及整表删除,alter表等操做,ROW格式会产生大量日志,所以在考虑是否使用ROW格式日志时应该跟据应用的实际状况,其所 产生的日志量会增长多少,以及带来的IO性能问题。)
缺点:因为记录的只是执行语句,为了这些语句能在slave上正确运行,所以还必须记录每条语句在执行的时候的 一些相关信息,以保证全部语句能在slave获得和在master端执行时候相同 的结果。另外mysql 的复制,
像一些特定函数功能,slave可与master上要保持一致会有不少相关问题(如sleep()函数, 1534555,以及user-defined functions(udf)会出现问题).
* SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)
同时在INSERT ...SELECT 会产生比 RBR 更多的行级锁
2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。
优势:binlog中能够不记录执行的sql语句的上下文相关的信息,仅须要记录那一条记录被修改为什么了。因此rowlevel的日志内容会很是清楚的记录下 每一行数据修改的细节。并且不会出现某些特定状况下的存储过程,或function,以及trigger的调用和触发没法被正确复制的问题
缺点:全部的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比 如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样形成binlog日志量会很大,特别是当执行alter table之类的语句的时候,因为表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。
3.Mixedlevel: 是以上两种level的混合使用,通常的语句修改使用statment格式保存binlog,如一些函数,statement没法完成主从复制的操做,则 采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,
也就是在Statement和Row之间选择 一种.新版本的MySQL中队row level模式也被作了优化,并非全部的修改都会以row level来记录,像遇到表结构变动的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,仍是会记录全部行的变动。
(2)适用场景
在一条 SQL 操做了多行数据时, statement 更节省空间, row 更占用空间。可是 row模式更可靠。
(3)结合第一个问题,每一种日志格式在复制中的优劣
Statement 可能占用空间会相对小一些,传送到 slave 的时间可能也短,可是没有 row模式的可靠。Row 模式在操做多行数据时更占用空间, 可是可靠。
6、下MySQL数据库cpu飙升到500%的话他怎么处理?
当 cpu 飙升到 500%时,先用操做系统命令 top 命令观察是否是 mysqld 占用致使的,若是不是,找出占用高的进程,并进行相关处理。若是是 mysqld 形成的, show processlist,看看里面跑的 session 状况,是否是有消耗资源的 sql 在运行。找出消耗高的 sql,看看执行计划是否准确, index 是否缺失,或者实在是数据量太大形成。通常来讲,确定要 kill 掉这些线程(同时观察 cpu 使用率是否降低),等进行相应的调整(好比说加索引、改 sql、改内存参数)以后,再从新跑这些 SQL。也有多是每一个 sql 消耗资源并很少,可是忽然之间,有大量的 session 连进来致使 cpu 飙升,这种状况就须要跟应用一块儿来分析为什么链接数会激增,再作出相应的调整,好比说限制链接数等
7、sql优化
(1)、explain出来的各类item的意义
id:每一个被独立执行的操做的标志,表示对象被操做的顺序。通常来讲, id 值大,先被执行;若是 id 值相同,则顺序从上到下。
select_type:查询中每一个 select 子句的类型。
table:名字,被操做的对象名称,一般的表名(或者别名),可是也有其余格式。
possible_keys:列出可能会用到的索引。
key_len:用到的索引键的平均长度,单位为字节。
ref:表示本行被操做的对象的参照对象,多是一个常量用 const 表示,也多是其余表的
filtered:rows*filtered/100 表示该步骤最后获得的行数(估计值)。
(2)、profile的意义以及使用场景
Profile 用来分析 sql 性能的消耗分布状况。当用 explain 没法解决慢 SQL 的时候,须要用profile 来对 sql 进行更细致的分析,找出 sql 所花的时间大部分消耗在哪一个部分,确认 sql的性能瓶颈。
(3)、explain 中的索引问题
Explain 结果中,通常来讲,要看到尽可能用 index(type 为 const、 ref 等, key 列有值),避免使用全表扫描(type 显式为 ALL)。好比说有 where 条件且选择性不错的列,须要创建索引。
被驱动表的链接列,也须要创建索引。被驱动表的链接列也可能会跟 where 条件列一块儿创建联合索引。当有排序或者 group by 的需求时,也能够考虑创建索引来达到直接排序和汇总的需求。
8、备份计划,mysqldump以及xtranbackup的实现原理
(1)备份计划
视库的大小来定,通常来讲 100G 内的库,能够考虑使用 mysqldump 来作,由于 mysqldump更加轻巧灵活,备份时间选在业务低峰期,能够天天进行都进行全量备份(mysqldump 备份
出来的文件比较小,压缩以后更小)。100G 以上的库,能够考虑用 xtranbackup 来作,备份速度明显要比 mysqldump 要快。通常是选择一周一个全备,其他天天进行增量备份,备份时间为业务低峰期。
(2)备份恢复时间
这里跟机器,尤为是硬盘的速率有关系,如下列举几个仅供参考
(3)备份恢复失败如何处理
首先在恢复以前就应该作足准备工做,避免恢复的时候出错。好比说备份以后的有效性检查、权限检查、空间检查等。若是万一报错,再根据报错的提示来进行相应的调整。
(4)mysqldump和xtrabackup实现原理
mysqldump 属于逻辑备份。加入--single-transaction 选项能够进行一致性备份。后台进程会先设置 session 的事务隔离级别为 RR(SET SESSION TRANSACTION ISOLATION LEVELREPEATABLE READ),以后显式开启一个事务(START TRANSACTION /*!40100 WITH CONSISTENTSNAPSHOT */),这样就保证了该事务里读到的数据都是事务事务时候的快照。以后再把表的数据读取出来。若是加上--master-data=1 的话,在刚开始的时候还会加一个数据库的读锁(FLUSH TABLES WITH READ LOCK),等开启事务后,再记录下数据库此时 binlog 的位置(showmaster status),立刻解锁,再读取表的数据。等全部的数据都已经导完,就能够结束事务
xtrabackup 属于物理备份,直接拷贝表空间文件,同时不断扫描产生的 redo 日志并保存下来。最后完成 innodb 的备份后,会作一个 flush engine logs 的操做(老版本在有 bug,在5.6 上不作此操做会丢数据),确保全部的 redo log 都已经落盘(涉及到事务的两阶段提交
概念,由于 xtrabackup 并不拷贝 binlog,因此必须保证全部的 redo log 都落盘,不然可能会丢最后一组提交事务的数据)。这个时间点就是 innodb 完成备份的时间点,数据文件虽然不是一致性的,可是有这段时间的 redo 就可让数据文件达到一致性(恢复的时候作的事
情)。而后还须要 flush tables with read lock,把 myisam 等其余引擎的表给备份出来,备份完后解锁。这样就作到了完美的热备。
9、mysqldump中备份出来的sql,若是我想sql文件中,一行只有一个insert....value()的话,怎么办?若是备份须要带上master的复制点信息怎么办?
--skip-extended-insert
[root@helei-zhuanshu ~]# mysqldump -uroot -p helei --skip-extended-insert
Enter password:
KEY `idx_c1` (`c1`),
KEY `idx_c2` (`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `helei`
--
LOCK TABLES `helei` WRITE;
/*!40000 ALTER TABLE `helei` DISABLE KEYS */;
INSERT INTO `helei` VALUES (1,32,37,38,'2016-10-18 06:19:24','susususususususususususu');
INSERT INTO `helei` VALUES (2,37,46,21,'2016-10-18 06:19:24','susususususu');
INSERT INTO `helei` VALUES (3,21,5,14,'2016-10-18 06:19:24','susu');
复制代码
10、500台db,在最快时间以内重启
可使用批量 ssh 工具 pssh 来对须要重启的机器执行重启命令。也可使用 salt(前提是客户端有安装 salt)或者 ansible( ansible 只须要 ssh 免登通了就行)等多线程工具同时操做多台服务器
11、innodb的读写参数优化
(1)读取参数
global buffer 以及 local buffer;
Global buffer:
Innodb_buffer_pool_size
innodb_log_buffer_size
innodb_additional_mem_pool_size
local buffer(下面的都是 server 层的 session 变量,不是 innodb 的):
Read_buffer_size
Join_buffer_size
Sort_buffer_size
Key_buffer_size
Binlog_cache_size
复制代码
(2)写入参数
innodb_flush_log_at_trx_commit
innodb_buffer_pool_size
insert_buffer_size
innodb_double_write
innodb_write_io_thread
innodb_flush_method
复制代码
(3)与IO相关的参数
innodb_write_io_threads = 8
innodb_read_io_threads = 8
innodb_thread_concurrency = 0
Sync_binlog
Innodb_flush_log_at_trx_commit
Innodb_lru_scan_depth
Innodb_io_capacity
Innodb_io_capacity_max
innodb_log_buffer_size
innodb_max_dirty_pages_pct
复制代码
(4)缓存参数以及缓存的适用场景
query cache/query_cache_type
并非全部表都适合使用query cache。形成query cache失效的缘由主要是相应的table发生了变动
第一个:读操做多的话看看比例,简单来讲,若是是用户清单表,或者说是数据比例比较固定,好比说商品列表,是能够打开的,前提是这些库比较集中,数据库中的实务比较小。
第二个:咱们“行骗”的时候,好比说咱们竞标的时候压测,把query cache打开,仍是能收到qps激增的效果,固然前提示前端的链接池什么的都配置同样。大部分状况下若是写入的居多,访问量并很少,那么就不要打开,例如社交网站的,10%的人产生内容,其他的90%都在消费,打开仍是效果很好的,可是你若是是qq消息,或者聊天,那就很要命。
第三个:小网站或者没有高并发的无所谓,高并发下,会看到 不少 qcache 锁 等待,因此通常高并发下,不建议打开query cache
12、你是如何监控大家的数据库的?大家的慢日志都是怎么查询的?
监控的工具备不少,例如zabbix,lepus,我这里用的是lepus
十3、你是否作过主从一致性校验,若是有,怎么作的,若是没有,你打算怎么作?
主从一致性校验有多种工具 例如checksum、mysqldiff、pt-table-checksum等
十4、表中有大字段X(例如:text类型),且字段X不会常常更新,以读为为主,请问您是选择拆成子表,仍是继续放一块儿?写出您这样选择的理由
答:拆带来的问题:链接消耗 + 存储拆分空间;不拆可能带来的问题:查询性能;
若是能容忍拆分带来的空间问题,拆的话最好和常常要查询的表的主键在物理结构上放置在一块儿(分区) 顺序IO,减小链接消耗,最后这是一个文本列再加上一个全文索引来尽可能抵消链接消耗
若是能容忍不拆分带来的查询性能损失的话:上面的方案在某个极致条件下确定会出现问题,那么不拆就是最好的选择
十5、MySQL中InnoDB引擎的行锁是经过加在什么上完成(或称实现)的?为何是这样子的?
例: select * from tab_with_index where id = 1 for update;
for update 能够根据条件来完成行锁锁定,而且 id 是有索引键的列,
若是 id 不是索引键那么InnoDB将完成表锁,,并发将无从谈起
十6、如何从mysqldump产生的全库备份中只恢复某一个库、某一张表?
全库备份
[root@HE1 ~]# mysqldump -uroot -p --single-transaction -A --master-data=2 >dump.sql
只还原erp库的内容
[root@HE1 ~]# mysql -uroot -pMANAGER erp --one-database <dump.sql
能够看出这里主要用到的参数是--one-database简写-o的参数,极大方便了咱们的恢复灵活性
那么如何从全库备份中抽取某张表呢,全库恢复,再恢复某张表小库还能够,大库就很麻烦了,那咱们能够利用正则表达式来进行快速抽取,具体实现方法以下:
从全库备份中抽取出t表的表结构
[root@HE1 ~]# sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `t`/!d;q' dump.sql
DROP TABLE IF EXISTS`t`;
/*!40101 SET@saved_cs_client =@@character_set_client */;
/*!40101 SETcharacter_set_client = utf8 */;
CREATE TABLE `t` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`age` tinyint(4) NOT NULL DEFAULT '0',
`name` varchar(30) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDBAUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
/*!40101 SETcharacter_set_client = @saved_cs_client */;
从全库备份中抽取出t表的内容
[root@HE1 ~]# grep'INSERT INTO `t`' dump.sql
INSERT INTO `t`VALUES (0,0,''),(1,0,'aa'),(2,0,'bbb'),(3,25,'helei');
复制代码
十7、在当前的工做中,你碰到到的最大的 mysql db 问题以及如何解决的?
能够选择一个处理过的比较棘手的案例,或者选择一个老师在课程上讲过的死锁的案例;没有及时 Purge + insert 惟一索引形成的死锁:具体案例能够参考学委笔记。
十8、请简洁地描述下 MySQL 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?
(1)事物的4种隔离级别
(2)不一样级别的现象
Read Uncommitted:能够读取其余 session 未提交的脏数据。
Read Committed:容许不可重复读取,但不容许脏读取。提交后,其余会话能够看到提交的数据。
Repeatable Read: 禁止不可重复读取和脏读取、以及幻读(innodb 独有)。
Serializable: 事务只能一个接着一个地执行,但不能并发执行。事务隔离级别最高。
不一样的隔离级别有不一样的现象,并有不一样的锁定/并发机制,隔离级别越高,数据库的并发性就越差。
最后
欢迎你们关注个人公众号【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。
前端