@TOC
mysql的三层架构:
第一层是管理客户端连接的。
对于每个客户端连接,都会从管理的线程池中取出一个为其服务
第二层是语句查询、语句解析、语句优化,一些select的缓存、还有内置函数、存储过程视图之类的管理。
查询语句的优化则是再内部的解析器对语句重构以提升执行效率。
第三层是存储引擎,主要负责数据的存取,建表时可以选择不同的引擎,不同的引擎各有优劣。
比如MyISAM不支持事务却使用表锁,innoDB使用行锁却支持事务。
并发控制
关于锁的上锁方式,分为两种:
一种是在第一层实现的显示上锁,但是其不在sql的标准范围。
另一种是在三层层引擎上实现的隐式上锁,详见本章事务部分。
锁的粒度主要是表锁(MyISAM引擎)和行锁(innoDB引擎)两种。
alter table之类的语句不论引擎,总是表锁。
事务
事务的原子、一致、隔离、持久。
关于隔离性的四个级别:
未提交读:只要执行了一条语句,不需要commit,这行语句的改变就可以被其他地方看到。
提交读(不可重复读):commit之前的所有修改对于其他地方都是看不到的
可重复读(mysql默认):保证了同一个事务读取一份数据是一致的。
事务A:select * from tableA
事务B:insert into tableA… 然后commit
事务A:select * from tableA
这样的情况下事务A读到的数据是不一样的,该隔离级别解决了这样(幻读)的问题。
串行:不如说是并发加上,每一行的的数据都会加锁执行.
innodb支持这四个隔离级别。
死锁的解决则是内部的死锁检测或者锁超时放弃,innoDB总是将持有锁最少的事务回滚,有的引擎则是放弃锁。
如果没有显示声明是一个事务,那么每条语句都视为一个事务,查询即提交,这是innodb的默认行为。
默认是SET AUTOCOMMIT=1,该值对于不支持事务的myisam或者memory是无影响的。
当这个值是0是时,会直到commit或rollback才提交。
alter table会强制commit当前正在执行的事务?还不清楚。
如果一个事务混用事务表(innodb)和非事务表(myisam):
成功执行不会有问题
失败回滚,而非事务型表是无法回滚的,在非事务表上执行事务,也不会有警告。
事务执行时,执行到哪锁上到哪,commit或者rollback时统一释放。
版本并发控制(另一种形式的锁)
版本号:
innodb中,该锁的实现通过每行记录的两个隐藏列实现,分别是创建时间和过期时间,但是存的数据并不是时间,而是一个叫版本号的东西,称作时间更容易理解。
在数据库中,有一个叫系统版本号的东西,每开始一个事务,都会导致该系统版本号自增,隐藏列就存这个东西。
一个事务开始时,首先记下系统版本号,作为自己的事务版本号:
select:
①只查找《创建时间版本号》小于等于《当前事务版本》的
②对于《删除时间版本号》,需要空,或者大于《当前事务版本》
insert:新行将《创建时间版本》设为《当前事务版本》
delete:不会真的删除,只是《删除时间版本》设为《当前事务版本》
update:
插入新行,设置为《创建时间版本》设为《当前事务版本》
修改旧行,《删除时间版本》设为《当前事务版本》
insert和delete的结合
以上操作通过数据的冗余和版本号的判断,使用空间换时间的方式,实现了非阻塞操作
一些引擎的概述:
尽量不混用多种引擎
innoDB:每个database或者schema都会是一个子目录,该目录下存储着建表的文件代码,文件名为:表名.frm。
使用版本并发控制来支持高并发,大量较短的事务执行、在线热备份、崩溃恢复
MyISAM:该引擎将表分为数据文件(.MYD)和索引文件(.MYI),日志、插入快,表锁、延迟写入文件
Archive:只支持select和insert。主要是对告诉的插入做了优化,日志
CSV:使用csv文件作,可以外部或者数据库直接写入和读取数据。
Memory:放在内存中,不进行IO,表锁,并发慢,hash表、查询快,不支持text类型,会被转为固定长度的char
转换表引擎:
①直接alter table,但是太慢
②导出表的文件,然后再导入新引擎的表,但是要主要导出或默认删原来的表
③建新表,insert into xx select …,加条件一部分一部分insert数据
2022年6月2日19:13:39
这章主要讲了一些分析服务器性能问题的东西,没好好看,以后还得来一遍,先写几个实用的东西
SHOW PROFILE
主要功能是记录执行了那些sql语句,然后可以在记录中查看某条sql语句读写磁盘、检查操作等等每个细节花费了多少时间。
set profiling = 1;
设置为1后,开始记录sql语句
show profiles;
显示所有记录的sql语句,每条记录包含《id,整条语句的执行时间,语句本身》
show profile for query 1;
显示id为1那条sql语句的详细数据,包括启动、打开表、上锁、权限检查、优化、创建临时表、执行、排序等等各个细致操作所花费的时间
需要注意的是,其默认行为是按执行顺序的,比如启动、打开,可以通过:
select state, sum(duration) as a from 库名.PROFILING where QUERY_ID=1 group by state order by a
来实现按操作的花费时间来显示,state列就是具体某个操作如打开、启动,但是这一列可能会有相同的,比如检查权限可能是多张表,然后用group来分组该列
SHOW STATUS
主要功能是返回一些计数器,有全局范围的,也有会话的。
FLUSH STATUS;
会将会话级别的计数器清理
执行某些sql语句
show status where Variable_name LIKE 'Handler%' or Variable_name LIKE 'Created%'
该行主要是看临时表临时文件还有一些句柄之类的东西,其各种变量意义随便搜了一个别人的链接,记下来备用吧
SHOW GLOBAL STATUS
主要是查看连接线程数、正在查询的线程数等等之类的信息。
提供的方案是每秒执行一次该命令来显示信息,不需要进入mysql,直接在命令行mysqladmin ext -i1
,i后面就是执行频率,然后可以用某些命令解析
以下命令,可以监控每秒的查询数、连接数、正在查询的线程数,以此推断出是哪里导致了服务器的停顿
mysqladmin extended-status -ri3
mysqladmin ext -i1 | awk '
/Queries/{q=$4-qp;qp=$4}
/Threads_connected/{tc=$4}
/Threads_runing/{printf "%5d %5d %5d\n",q, tc, $4}'
mysqladmin ext -i1 | awk '/Queries/{q=$4-qp;qp=$4}/Threads_connected/{tc=$4}/Threads_runing/{printf "%5d %5d %5d\n",q, tc, $4}'
通用原则
尽量选择更小的类型
对于IP地址,使用INET_ATON()
和INET_NTOA()
避免NULL,使用NOT NULL。
NULL变为NOT NULL并不会有显著性能提升,但是在列上建索引的话,就会有。
NULL值会导致索引统计变得复杂、更多的存储空间以及特殊处理,当可为NULL的列设为索引是时,更需要额外的字节,在MyISAM中还可能导致《原来固定长度的索引》变为《可变长度的索引》。
避免太多的列,执行语句时,《服务器层》通过行缓存从《引擎层》拷贝数据,然后在服务器层将这些经过编码的数据转换成对应类型,而需要转换的列越多,相应的代价烨越大。
查询语句关联的数量,mysql将关联操作设为最多61张表,然而建议是单个查询不要超过12个表关联。
范式还是反范式:
范式即多表,没有冗余的数据,但取数据时需要多表联查
反范式即不分表,一张表里有冗余数据,但是不需要联查
又或者混用,多表存储某列相同的数据,但更新时需要更新多个表
需要频繁统计之类的,设置专门的计数表、列等,并在插入删除时维护,以避免count函数带来的开销
一些加快ALTER TABLE操作的方式,但是不被mysql支持:
大部分ALTER TABLE会导致表的重建,即建新表、复制数据、删酒标,但烨不是所有。
例如MODIFY 列名
会导致表的重建,但是ALTER TABLE
下的ALTER COLUMN
不会。
1.替换修改表的.frm文件(InnoDB)
建一张结构相同的新表
执行:FLUSH TABLES WITH READ LOCK,关闭所有正在使用的表,并禁止打开新表。
新表的.frm文件和旧表的.frm文件互相改名替换
UNLOCK TABLES解锁
2,MyISAM载入数据
先关闭索引,然后导入索引,再重新建立索引
标识列的选择
最好使用整型,避免字符串。
避免使用随机数做标识列,如MD5、SHA1等,随机的数值导致不同的行分布在很大的空间内,导致select、insert等变慢等。
整型
TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT
是,分别使用8、16、24、32、64字节存储。
可选的UNSIGNEDSHUXING
整数计算都会转成BIGINT操作,32位环境也是,一些聚合函数则转成实数计算。
使用如INT(11)并不会真的导致只有11位空间,还是按int算,但是在显示的时候只显示11位的值。
实数
FLOAT
和DOUBLE
是标准的浮点近似运算。
DECIMAL
则是不会丢失的高精度计算,如存储钱,由mysql服务器实现,相比于标准浮点更慢。
DECLMAL(18, 9)
表示总共18个数字,小数部分有9位精度。
MYSQL将该类型打包大一个二进制字符串,每4个字节存9个数字,也就是说DECLMAL(18, 9)
占4+4+1字节,1字节是小数点。
百度查的是18+2个字节,可能是因为书中说明MYSQL版本5.0以上才将其打包位二进制字符串的原因。
最好的方式是使用BIGINT
来存DECIMAL
的数据,使用的时候根据小数位数来算出实际数据,既避免标准浮点的精度丢失,又避免DECIMAL
的运算慢。
字符串
首先,字符串VARCHAR
和CHAR
在不同的引擎中表现是不一样的。
VARCHAR
:变长字符串。
只使用需要的空间,例外是建表时使用ROW_FORMAT=FIXED,则全是定长。
另外需要额外的空间存字符串的长度,长度字段需要的空间根据实际存储的空间变化。如10字节需要1字节的长度,150字节则需要2字节的长度空间
缺点:当update语句导致字符串需要的空间的增长时,额外的空间处理,在MyISAM引擎将其拆成多段处理,InnoDB则是分裂页,使该行可以放入,InnoDB还可以将其转为BLOB二进制处理。
使用场景:该列更新少、使用了复杂字符集(URF-8)、定义的最大长度比平均长度大很多。
CHAR
:定长字符串。
BINARY
和VARBINARY
:和前面两个的区别是这两个存二进制,而不是字符,比较时更快、大小写敏感。
在MYSQL5.0以前,字符串末尾的空格总是会被删除,而之后,CHAR的末尾空格会被抹掉,而VARCHAR不会被抹去,memory表对于VARCHAR总是以最大空间分配。
BLOB和TEXT
占用空间大的数据专用。当空间过大,InnoDB使用指针指向外部的存储区域。
BLOB
存储二进制数据,TEXT
存超长文本数据。
对于这两个类型的排序,只比较前MAX_SORT_LENGTH
个字节,而不是全部,或者用ORDER BY SUBSTRING(column,length)
MEMORY引擎不支持BLOB和TEXT类型,如果临时表有这样的列,则会导致使用MyISAM存储临时数据。或者使用ORDER BY SUBSTRING
就可以使用内存表了,但是要确保子串足够短。
枚举
列名 ENUMM(‘a’, ‘b’, ‘c’)
枚举字段存储的是整数而不是字符串,排序也是按整数而不是字符串
缺点是增加枚举的新字段需要使用ALTER TABLE,对大表很麻烦。
后略,更多时候会使用INT代替枚举吧。
时间
DATETIME
:范围是1001年到9999年,精度秒,数据封装到YYYYMMDDHHMMSS的整数格式。但显示时是标准显示。
TIMESTAMP:UNIX
时间戳,需要注意时差。
位数据
BIT
可以用BIT(N)来明确位数的长度,最多64
MyISAM引擎将不同行的bit打包在一起节省空间。
InnoDB则使用int存每个bit。
BIT在MYSQL被视为《01的二进制字符串》,而不是《数字》,select时,将该《二进制》转为《字符串》显示,也就是说如果存了一个“00111001”,其对应的ASCII码是9,直接select该列显示9,转成数字显示5。
SET
同样是位运算,提供一组函数,但改变代价是ALTER TABLE。
2022年6月13日18:52:54
5.1索引的类型
主要是B树索引和哈希索引两种
重要的事:《一个索引包含多个列》和《多个索引都只包含一个列》的优化是完全不一样的,前者可以在说明B树索引的部分看到
key(列1, 列2, 列3)
select * from XXX where 列2=xxx
select * from XXX where 列1=xxx 列3=xxx
,那么只有列1的排序能用上
key(列1, 列2)
:这样建立的索引是,是由列1、列2两个作为参数计算hash值,如果where里只有一个条件,那么无法计算出hash值,这个索引带来的优化也就用不上了
CRC32(列1)
生成一个32位的hash值,代价有两个,一是插入和更新是维护这个值,二是 selete * from XXX where 列1=xxx and MYHASH=CRC32(列1)
来防止hash冲突
5.2索引的原理及数据的分布
数据增删后导致的各种空间碎片问题,可以使用OPTIMIZE TABLE
或者导入再导出来解决,又或者不支持OPTIMIZE,可以用ALTER TABLE 表名 ENGINE=原来的引擎名
即可。
瞎写点东西,实习的时候,看到数据库里全是MyISAM引擎,每张表里都有一个与数据无关自增的索引,首先MyISAM不支持聚簇,因为数据总是按序写在磁盘,其次也仅仅是将其设为普通索引,为什么要这样做?后来写东西的时候倒也有用到,很多时候程序里处理过的写回数据库时,直接用这个ID作为条件,其他倒是没怎么用到。
5.3建立索引的策略
count(distinct 列名1) / count(*)
key(money)
时,如果使用 select * from XXX where money*2=10
,是无法使用索引带来的性能提升的,是一个全表扫描,所以应该尽可能避免表达式,而使用独立的列名作为where条件
0.03
0.03
的长度
还需要注意数据的特殊性,比如说选择了前5个字符,但是表中又有大量的数据前5个字符一样,那么索引的效率也会降低,对于特殊数据,当然也得有特殊的处理。
key(列1)
select 列1 from XXX
,那么不需要再回表查,因为列1索引的B树,已经存储了列1的值,也就不需要再根据主键ID到聚簇的B树里去查了。
select * from XXX where 列3=x and 列4=x
,可以改为 select * from XXX JOIN(select 列1 from XXX where 列3=x and 列4=x )AS YYY ON(XXX.列1=YYY.列1)
key(列1, 列2, 列3)
这样的索引,如果where条件没有列1,直接 where 列2=xxx
,索引是无法生效的,如果在 order by 列2
又会如何,当然也是无法生效的。
where 列1=xxx order by 列2
,是可以生效的,因为B树中先按列1排序,当指定了列1的值,那么范围也确定了,这个范围内按列2排序,所以索引是可以生效的。
索引列的条件尽可能放左边,范围查询放右边。
2022年6月13日21:02:37
慢查询:即查询很慢的语句,超过long_query_time
被视为是慢查询,默认值10秒。
首先是不需要的列和重复的查询,select *是应该被避免的,而对于复用性强的数据,是否应该缓存在应用层,而不是依赖于mysql的缓存(查询需要经过网络传输和缓存失效的可能)。
查询的优化离不开索引,上一章和这里相似,再来一遍。
1.引擎层,使用索引先一步过滤到大量的数据,就可以避免无关数据被扫描和上锁
2.服务层,使用覆盖索引,直接从对应索引的B树找到数据返回,而不需要再去主键查一次。
3.服务层,没有索引,大多数时候是全表扫描或者大量无关数据被返回出来,再通过where筛选。
对于group by语句,应当考虑是否有一张独立的统计表。
对于数据量大的语句,考虑是否将任务拆分,每隔一段时间来操作一部分数据,如limit 10000,避免长期对锁的持有
对于多表查询,是否应该将其分裂为多个子查询,会带来:
1.缓存命中率高,最直接的就是,一个多表查询的结果缓存,一旦其中一个表有改变,可能整个缓存都不能用了,而单表查询的结果缓存就不会了。
2.减少锁的竞争。
3.如果在应用层对这些单表缓存,使用map或者hash_map对其进行hash关联会不会更有效率?
1.客户端把这条查询通过一个半双工的协议发给服务器,然后客户端剩下的就只有等待了。
需要注意的是,当某个语言里调用mysql的接口去请求查询,只要接口返回,数据就已经保存在本地缓存了,而不是取数据的时候现查。
2.服务器检查缓存,如果缓存有,就直接返回而不执行任何操作。
3.对sql解析、预处理,再由优化器生成执行计划。
解析器是检查语法规则、关键字、引号等是否匹配。
预处理则是检查表、列是否存在,是由有权限等。
查询优化:表关联的顺序、外连接转为内连接、条件等价变换、索引覆盖等。
最终生成执行计划,是一串API、命令。
4.调用存储引擎的API执行这一串命令完成查询。
5.查询结果发给客户端。
只要有一条结果被查询出来,就开始向客户端发,而不是等全部结果一起发。
where in子查询,使用INNER JOIN或EXISTS子查询代替
没有具体的方式,应该具体测试INNER JOIN快 还是 EXISTS子查询快。
如果有等值传递,对于in列表的所有数据都会复制到其他条件一份,而当in列表非常大时…
UNION
对于两个查询的合并,如果要limit
,应该每个select的查询都有一个limit
,否则就会返回全部的结果集,然后再取前多少条。
同样的,所有的where条件在每个select中也应该有一份,便于优化器优化。
尽可能使用UNION ALL
,否则就会加上DISTINCT选项,导致对表做唯一性检查。
MIN、MAX优化
select min(id) from 表1 where name=‘xxx’
改为
select id from 表1 USE INDEX(PRIMARY) WHERE name=‘xxx’ limit 1;
如果name列没有索引,就会导致全表扫描,而主键字段ID是排序的,那么只要找到第一个条件满足的,那么它就是最小的
count优化
对于MyISAM,只有在没有where时才会很快,否则就是全表或者使用了索引
select count(*) from 表名 where id > 5
改成
select (select count(*) from 表名) - count(*) from 表名 where id <=5
只扫描前5行,而不用扫描5之后的行
limit优化
对于limit 1000,20这样的查询,会查询前1020条,然后显示那20条
如果真的需要真的需要分页,那么最简单的应该是记录下主键ID,然后where + limit
一些指定查询方式的命令
HIGH_PRIORITY
和LOW__PRIORITY
只对表锁起作用,在行锁表中使用会导致表锁而降低性能。
HIGH总是将任务放到最前面执行,LOW只要前面有任务,就不执行
可用于insert或select。
DELAYED
对于insert和replace有效,数据放到缓存中
客户端可以直接看到,数据库则在空闲时写入。
STRAIGHT_JOIN
放在select开头:所有的表都按出现顺序关联
放在select两个关联表的中间:两个表按顺序关联。
SQL_SMALL_RESULT
和SQL_BIG_RESULT
只对select有效,对于查询结果,分别告mysql结果集很大或者很小,临时表分别放在磁盘或内存中
SQL_BUFFER_RESULT
查询结果放在临时表中,然后尽早释放表锁。
SQL_CACHE
和SQL_NO_CACHE
是否将结果放在缓存中。
SQL_CALC_FOUND_ROWS
一个select加上limit后,只显示前多少条,该关键字返回在limit之前总共查了多少行。
FOR UPDATE
和LOCK IN SHARE MODE
只对行锁有效,看不懂干嘛的。
USE INDEX
、IGNORE INDEX
、FORCE INDEX
使用某个索引或者不使用索引。
关于用户自定义变量
set @var1 := 1;
生命周期在一个连接内有效
可以用作各种条件但不是不能做表名、列名之类的
:=优先级很低,复杂表达式应使用括号。
使用未定义变量不会有错误。
在select中,可以不断修改自己来为下一行输出提供新值
可以where xxx=xxx AND var1:=999
2022年6月21日13:25:49
创建表分区表的例子
create table sales(
order_date DATETIME NOT NULL
)ENGINE=InnoDB PARTITION BY RANGE(YEAR(order_date))
(
PARTITION 默认分区 VALUES LESS THAN (0), // 条件null的插入会被丢到这里
PARTITION 分区1的名字 VALUES LESS THAN (2001),
PARTITION 分区2的名字 VALUES LESS THAN (2002),
PARTITION 分区3的名字 VALUES LESS THAN (2003)
)
YEAR(order_date)
EXPLAIN SELECT * FROM 视图名
PRIMARY是合并算法,DERIVED是临时表算法。
insert into tb1(co1, co2) values('a', 'b')
insert into tb1(co1, co2) values(?, ?)
character_set_client
转为 character_set_cinnection
character_set_cinnection
character_set_cinnection
转为 character_set_client
LENGTH()
返回字节数, CHAR_LENGTH()
返回字符数。
FLUSH QUERY CACHE
整理碎片。
SQL_CACHE
才会缓存。
SQL_NO_CACHE
来表示不缓存
Qcache_free_memory
,如果剩余的空间多,说明是内存碎片
Qcache_lowmem_prunes
增长快
2022年6月21日16:39:04
一个阉割版但是《够用》的配置文件(略有修改),后面篇幅基本都基于此
[mysqld]
# GENERAL
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
pid_file = /var/lib/mysql/mysql.pid
user = mysql # 哪个系统用户启动mysqld,需要存在且有权限
port = 3306
default_storage_engine = InnoDB
# INNODB
innodb_buffer_poll_size = 自定义的值 # innodb最依赖的选项,见后:InnoDB的配置
innodb_max_dirty_pages_pct = 0 # 脏页百分比,超过该值时,把缓存刷到批判
innodb_log_file_size = 自定义的值 # 默认是5MB,大多数时候128M足足足够了
innodb_file_per_table = 1 # 将数据存到某个具体的表空间文件,而不是由mysql管理,鸡肋
innodb_flush_method = O_DIRECT
innodb_flush_log_at_trx_commit = 0、1、2 # 详见后:InnoDB的事务日志
# MyISAM
key_buffer_size = 自定义的值
myisam_block_size = 最好填一个和操作系统页大小相同的值
# LOGGING
log_errror = /var/lib/mysql/mysql-error.log
slow_query_log = /var/lib/mysql/mysql-slow.log
# OTHER
tmp_table_size = 32M # 临时表(memory引擎)的最大大小,超过会导致磁盘表
max_heap_table_size = 32M # 临时表(memory引擎)的最大大小,超过会导致磁盘表
query_cache_type = 0
query_cache_size = 0
max_connections = 自定义的值 # 最大的连接用户数量
thread_cache = 自定义的值 # 连接线程池的连接数量(当前有的)
thread_cache_size = 自定义的值 # 连接线程池的连接数量(可容纳的)
table_cache = 自定义的值
open_files_limit = 65536
[client]
user = mysql
port = 3306
一些其他的配置选项
expire_logs_days # 保留多少天的二进制日志
max_allowed_packet # 控制数据包的最大大小,包含发生和接收
max_connect_errors # 可以设的大,防止网络波动,客户端频繁发起连接而被拉入黑名单(每隔一段时间移除)
skip_name_resolve # 跳过dns查找
sql_mode # 很多选项
read_only # 禁止《无特权用户变更》,即备库,只接受主库传来的变更
skip_slave_strat # 禁用自启动
salve_net_timeout # 主备库断连后,重连的间隔,默认1小时,可以设的短
innodb # 若设为FORCE,只有在支持innodb时才启动
innodb_autoinc_lock_mode # 0:对于自增列的锁定,insert结束才释放
# 1:默认,拿到新的自增值后,自增列锁就释放
# 2:不上锁,得到的值可能不连续
innode_buffer_pool_instances # 把缓存池切成多块,锁竞争没那么厉害
innodb_io_capacity # 每秒多少次IO到磁盘?看不太懂
innodb_read_id_threads # 默认4,后台有几个读线程
innodb_write_id_threads # 默认4,后台有几个写线程
innodb_strict_mode # 让警告变为报错
innodb_old_blocks_time # 全表扫描多时,设置大点,否则设小点
which mysqld
,输出 /usr/sbin/mysqld
(可能会不同)
/usr/sbin/mysqld --verbose --help | grep -A 1 'Default options'
,输出配置文件的位置
innodb_buffer_poll_size
、 key_buffer_size
之类的。
innodb_buffer_poll_size
很重要,因为这个空间存放着行缓存、索引、缓冲区(延迟写入)、锁等等很多结构。
innodb_max_dirty_pages_pct
时同步。
key_buffer_size
select sum(INDEX_LENGTH) from INFORMATION_SCHEMA.TABLES WHERE ENGINE='MYISAM'
key_buffer_size
一个值。
myisam_block_size
,当修改的数据到了操作系统的缓存上,操作系统的缓存又要和磁盘同步, myisam_block_size
和 操作系统的页大小
相同,会带来效率的提升。
innodb_log_file_size
。
innodb_flush_log_at_trx_commit
:
innodb_flush_method
:
innodb_flush_method
,会导致IO操作无法合并,多次调用fsync,详见后InnoDB表空间。另外,还会导致双重缓存,即mysql内部缓存一遍日志,数据经过fsync,又会在操作系统上缓存一遍。
2022年6月24日16:49:49
看不懂,以后再看吧。
grant replication slave, replication client on *.* to shh_test@'192.168.0.%' idenified by '12345678';
show master status;
来查看到底是什么文件名。
log_bin= /var/lib/mysql/mysql-bin
server_id= 10
ID的主要目的是避免循环复制。
sync_binlog=1
该行导致事务commit之前先写二进制日志防止丢失,但是只对库上的《 二进制日志》有效,对于备库上拉来的《 中继日志》无效。
log_bin= mysql-bin
server_id= 11
relay_log= /var/lib/mysql/mysql-relay-bin
《二进制日志》从主库拉到备库存储的目录、文件名
log_slave_updates= 1
有点看不懂,但是最好设置,备份操作本身的命令也记录到日志之类的?
read_only= 1
skip_slave_start
备库崩溃重启后,有该选项,将阻止继续同步主库的数据,以防止损坏后没有机会恢复
sync_master_info=1
最后三个sync,《 中继日志》是不安全的,崩溃后,中继日志丢失,这些操作用来同步《 中继日志》到磁盘防丢失。
sync_relay_log=1
sync_relay_log_info=1
change master to
MASTER_HOST='主机名字或ip',
MASETER_SUER='shh_test',
MASTER_PASSWORD='12345678',
MASTER_LOG_FILE='mysql-bin.00001',
MASTER_LOG_POS=0;
start slave;
show slave status;
可以查看备库工作的详细信息。
change master to
,细节也在15章。
stop slave
,否则kill掉正在update的线程,导致主备不一致。
2022年7月11日12:01:31