geekbang-Mysql实战笔记

Mysql实战笔记

一.基础篇

1.基础架构
server层
存储过程、触发器、视图都在server层这里实现

***1.连接器***
与客户端建立连接
	获取权限,连接建立之后,中途更新权限,权限不变,需要重启才能获得新的权限。
	维持和管理连接:一般使用长连接定期断开长连接,mysql5.7之后使用mysql_reset_connection重新初始化连接资源
*2.查询缓存*
	mysql8.0去除了这个功能;
	每一次update都会清空缓存的。
	静态不变的查询才使用缓存
*3.分析器*
	词法分析
	空格 关键字 字符串识别
	语法分析
	判断是否满足mysql的语法
*4.优化器*
	多个索引决定使用哪个索引
	多个表连接决定使用各个表的连接顺序
*5.执行器*
	判断是否有表的权限
	根据引擎提供的接口取表的数据
	组装所有的结果集返回给客户端
	rows_examined表示引擎扫描的行数

存储引擎层
负责数据的存储和提取

	插件式架构
	mysql5.5默认存储引擎为InnoDB
	引擎分类:InnoDB,MyISAM,Memory

2.日志系统
1.redo log 重做日志

	mysql的WAL【write ahead logging】先写日志,再写磁盘
	crash-safe:数据库异常重启,之前提交的记录不会丢失
	InnoDB引擎特有的日志
	物理日志:记录在某个数据页上做了什么修改

2.binlog 归档日志

	mysql自带server实现的日志
	逻辑日志:记录语句的原始逻辑,比如:给ID=2这一行的c字段加1
	数据库扩容/增加备份库-常见做法
	全量备份+binlog日志

3.两阶段提交

引擎中执行redo-log到prepeare状态,写binlog日志,redo-log提交事务到commit状态;
建议设置,保证每次事务提交之后保存到磁盘
	innodb_flush_log_at_trx_commit=1
	sync_binlog=1

update语句的内部执行流程

1.执行器调用引擎接口查询id=2的行,如果内存中有直接返回,没有则查询磁盘
2.执行器拿到引擎的行数据执行update操作进行N=N+1,再调用引擎写入磁盘
3.引擎将这行数据更新到内存中,同时更新操作记录到redo-log并处于prepare状态,随时可以提交事务
4.执行器生成这个操作的bin-log日志,并把bin-log日志写入磁盘
5.执行器调用引擎接口提交事务,redo-log状态改为commit状态,更新完成。

3.事务隔离

事务的特性ACID:
原子性 Atomicity
一致性 Consistency
隔离性 Isolation
持久性 Durability
多事务同时执行,可能出现的问题:**脏读、幻读、不可重复读**

事务的隔离级别

读未提交 read uncommitted:
	一个事务还没有提交,它的变更操作就能被其他事务看到
	直接返回记录的最新值,没有视图的概念
读提交 read committed:
	一个事务提交之后,它的变更才能被看到
	在sql开始执行的时候创建事务
可重复读 repeatable read:
	一个事务执行过程看到的数据跟这个事务在启动时候看到的数据时一致的。未提交的事务对其他事务也是不可见的
	事务启动的时候创建视图,整个事务期间使用该视图
串行化 serializable:
	对于同一行记录,写会加写锁,读会加读锁。读写锁冲突的时候,后访问的事务必须等待前一个事务执行完成,才能继续执行
	加锁避免其他访问

总:隔离级别越来越高,效率越来越低
配置方式
transaction-isolation = READ-COMMITTED
show variables
事务的隔离的实现原理

实际上每条记录在更新的时候都会同时记录一条回滚操作。记录上的最新值,通过回滚操作,可以得到前一个状态的值。
数据库的多版本并发控制  MVCC
系统判断当没有事务再需要用到这些回滚日志的时候,就会删除这些回滚日志。
系统中没有比这个回滚日志更早的read-view的时候。
尽量避免使用长事务,长事务会占用存储资源,占用锁资源,也可能拖垮整个库。

事务的启动方式

	显示启动
		bigin/start transaction
		commit
		rollback
set autocommit=0  关闭这个线程的自动提交 commit/rollback结束事务
set autocommit = 1  自动提交事务;如果考虑多一次交互问题,可以使用commit work and chain语法,即提交事务并自动启动下一个事务
**监控查询超60s长事务**
select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60

4.索引
索引的出现其实就是为了提高数据的查询效率,就像书的目录一样
4.1 索引常见的模型:
1.哈希表:key-value,相同的hash值,则采用链表的形式连接在对应的key后面
2.有序数组:在等值查询和范围查询场景中的性能就都非常优秀;有序数组索引只适用于静态存储引擎
3.N叉搜索树:N=4int/13=16k/13=1204;数的高度是固定的;减少磁盘的访问次数。;存储计算,树高为4,则1200^3=17亿
4.2 innoDB索引模型
主键索引 – 聚簇索引 clustered index:主键索引叶子节点存的是整行的值
非主键索引 – 二级索引 --secondary index:叶子节点上存储的是主键的值
区别:非主键索引会多一次回表,主键索引直接查询结果
4.3 索引的维护

1.中间插入需要挪动后面的数据,空出位置
2.数据页已用完则需要申请新的数据页,然后挪动部分数据到新的页,这个过程叫页分裂,空间利用率降低50%
3.页合并

4.4索引分类

1.覆盖索引:覆盖索引可以减少树的搜索次数,显著提高查询性能,所以使用覆盖索引是一个常用的性能优化手段,查询字段正好全部是索引列
2.最左前缀原则:联合索引的最左N个字段,也可以是字符串索引的最左M个字符
3.索引下推:mysql5.6之后,可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤不满足条件的记录,减少回表的次数。
					将原来多次调引擎层,在server层处理数据,下推到引擎层处理一次调用过滤处理。

5.锁
5.1全局锁
场景:全库逻辑备份
mysql提供 FTWRL-- flush tables with read lock 加全局锁
mysql官方逻辑备份工具:mysqldump=single-transaction;数据库支持事务引擎
5.2表锁
1.元数据锁 meta data lock,MDL:读锁之间不互斥;读写锁,写锁之间是互斥的,用来保证变更表结构操作的安全性
2.如何安全地给小表加字段:kill长事务;alter table 语句里面设定等待时间,如果指定时间里面能够拿到MDL写锁最好,拿不到也不会阻塞后面的业务语句,先放弃。后面在重试次命令
5.3 行锁
行锁时针对数据表中的行记录的锁,事务A更新了一行,而这时候事务B也要更新同一行,则必须等待事务A的操作完成后才能进行更新
1.两阶段锁:innoDB事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,而是要等到事务结束时才释放;
如果事务中需要锁多个行,要把最可能造成锁冲突、最可能影响并发度的锁尽量往后放。
2.死锁:并发系统中不同线程出现循环资源依赖,涉及的线程都是在等待别的线程释放资源,就会导致进入无线等待的状态,即死锁。
解决策略:a.直接进入等待,知道超时。innodb_lock_wait_timeout设置时间,默认为50s;
b.发起死锁检测,发现死锁,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行,innodb_deadlock_detect=on
3.死锁检测问题:
热点行更新导致的性能问题:
a.临时把死锁检查关闭–业务有损
b.控制并发度:中间件实现;优化mysql源码,对于相同行的更新,在进入引擎之前排队.

6.事务
innoDB支持RC和RR隔离级别实现是用的一致性视图(consistent read view).
事务在启动的时候会拍一个快照,这个快照是基于整个库的.
6.1事务是如何实现MVCC?
1.每个事务都有一个事务id,叫transaction id 递增
2.事务在启动时,找到已提交的最大事务id记为up_limit_id
3.事务在更新一条语句时,如id=1改为id=2,会把id=1和该行之前的row_trx_id写到undo_log里,并且在数据页上把id的值改为2,并且修改这条语句的tranaction id 记在该行行头。
4.再定一个规矩,一个事务要查一条数据时,必须先用该事务的up_limit_id与该行的transcaction_id做对比,如果upLimitId>=transcactionId则可以看,否则只能去undoLog里面取。在undoLog里面,如果upLimitId>transcationId则返回数据。
6.2 什么是当前读:
由于当前读都是先读后写,只能读当前的值,所以为当前读.会更新事务内的upLimitId为该事务的transactionId
6.3:为什么rr能实现可重复读,而rc不能,分两种情况:
a.快照读的情况下,rr不能更新事务内的upLimitId,而rc每次都会把upLimitId更新为快照读之前最新已提交事务的transactionId,则rc不能可重复读
b.当前读的情况下,rr是利用recordLock+gapLock来实现的,而rc没有gap,所以rc不能可重复读

实践篇

1.唯一索引还是普通索引
1.1.查询过程:
普通索引查找到满足条件的第一个记录后,需要查找下一个记录,直到碰到第一个不满足条件的记录
唯一索引查到第一个满足条件的记录后就会停止继续检索
普通索引多一次指针的寻址和一次计算
1.2更新过程
1.innoDB会将更新操作缓存在 change buffer 中
2.使用change buffer 减少磁盘读取,语句的执行速度会明显提升;提高内存利用率
3.change buffer什么时候使用?
a.唯一索引不适用change buffer
b.普通索引使用
c.写多读少,change buffer收益明显
d.写完马上就的读,change buffer反而其副作用
4.如果需要更新的记录不再目标页中
唯一索引,需要将数据页读入内存,判断到没有冲突,插入这个值
普通索引,将更新记录在change buffer,语句结束,后台线程merge到磁盘
1.3索引选择
1.查询能力上面是没有区别的,更新性能上有影响;建议使用普通索引
2.对于历史数据表,可以把唯一索引改为普通索引,提升查询性能
1.4 change buffer & redo log
change buffer 主要节省随机读磁盘的IO消耗
redo log 主要节省随机写磁盘的IO消耗

2.mysql为什么会选错索引
2.1优化器的逻辑
1.优化器选择索引的目的是找到一个最优的方案去执行sql
2.扫描行数:
a.扫描行数越少,磁盘访问次数越少,消耗cpu资源越少
b.根据统计信息来估算记录数
c.统计信息–索引的区分度:同一个索引上不同值的个数,我们定义为基数,基数越大,索引区分度越大
d.mysql如何得到索引的基数?:采样统计;innoDb默认选择N个数据页,统计这些页上的不同值,得到一个平均值,然后乘这个索引的页面数,就得到这个索引的基数;当变更的数据行数超过1/M的时候,就会触发重新统计
e.如何判断扫描行数:普通索引扫描行数需要回表,主键索引不需要回表,优化器会估算这两个值的代价,优化器可能选择主键索引扫描行数多来执行
f.explain不准?:analyze talbe t 可以重新统计索引信息
3.是否使用临时表
4.是否排序
2.2 索引选择异常实践解决方案
1.采用force index强行选择一个索引:
mysql会在候选索引列表中直接选择这个索引,不再评估其他索引的执行代价;
风险:写法不优美;如果索引改名,语句得重写;pro环境需要测试再发布,代价大。
2.修改sql语句,引导mysql使用我们期望的索引:
根据实际的数据特征进行相关诱导优化器重新选择索引
3.删除误用索引或者增加更合适的索引

3.怎么给字符串字段加索引?
3.1 前缀索引
1.定义好长度,就可以做到既然节省空间,又不用额外增加太多的查询成本
2.使用select count(distinct left (emai,4)…from t 来统计索引基数,同时根据自定义的损失比例来定义前缀索引的长度
3.使用前缀索引就用不上覆盖索引对查询性能的优化了
3.2倒序存储 reverse()
1.不支持范围查询
2.额外调用一次reverse()函数
3.还是前缀索引的形式,可能增加扫描行数
3.3 hash字段 crc32()
1.不支持范围查询
2.额外调用crc32()函数,复杂度比reverse()高,消耗cpu多一点
3.需要额外增加一个字段,可能出现冲突

4.mysql的抖动?
4.1现象
同一条sql在数据库有时候会很慢,这个情况是随机的,不好复现,这种感觉就像是数据库抖了一下
4.2概念
当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”。内存数据写入到磁盘后,内存和磁盘保持一致了,称为“干净页”
4.3 原因
flush 刷脏页,即将内存数据同步到磁盘
4.4场景
1.redo log写满了,需要flush
2.内存不够用了。
a.页分类:未使用的页,脏页,干净页
b. 内存方式:innoDB采用缓冲池buffer pool管理内存。
c. 明显影响性能的情况:
一个查询要淘汰的脏页个数太多,会导致查询的响应时间明显变长
日志写满,更新全部堵住,写性能跌为0,敏感业务不能接受
d. innodb_flush_neighbors=0
取消连坐刷脏页,只刷自己的脏页

5.数据库的表空间的回收
5.1 表结构占用的空间极少
5.2 表数据
innodb_file_per_table=OFF 表数据存在系统共享空间,跟数据字典放在一起;
innodb_file_per_table=ON,每个innoDB表数据存储在一个以.ibd为后缀的文件中 (5.6默认)
5.3 数据的删除流程:
1.innoDB只会把记录标记为删除,该记录可以复用,磁盘空间不变。
2.delete 命令其实只是把记录的位置,或者数据页标记为"可复用",磁盘文件的大小是不会变的,没有回收表空间。可以复用的空间,像空洞
3.随机插入数据也会造成空洞,造成索引的数据页分裂
5.4 重建表
1.重建表 可以去除空洞
2.alter table A engine=InnoDB:新建与表A结构相同的表B;将A的数据一行一行copy到B,用B替换A;
3. 5.6之后的On-line DDL:copy途中记录更新在一个row log日志文件,导入B的时候应用日志操作。过程中copy数据的时候,MDL的写锁会退化成读锁,保证不阻塞
5.5 inplace
1.DDL的过程如果是Online的,就一定是inplace的
2.inplace的DDL,有可能不是Online的,ex:添加全文检索(fullTextIndex)和空间索引(spatialIndex)
3.inplace会阻塞增删改查操作

6.count(*)
6.1 MyISAM:会把表的总行数存在磁盘上,因此执行count()就会直接返回,效率高
6.2 InnoDB
1.需要把数据一行一行的从引擎里面读出来,然后累积计数
2.因为多版本并发控制MVCC,innoDB不确定应该返回多少行,所以是基于某次查询的可见行做累积的。
3.优化-优化器会找到最小的那颗树来遍历统计。减少扫描的数据量是数据库的通用设计法则之一
4.show table status中的行数不一定准确,官方文档说误差在40%-50%
5.如何计数比较准确
a.缓存:丢失更新;异常重启,重新刷新缓存即可,可以被接受的
逻辑上存在不精确的缺陷;并发系统中,我们无法精确控制不同线程的执行时刻.两种不同的存储系统不支持分布式事务
b…统计表:利用数据库原有的事务即可。innoDB是支持崩溃恢复不丢数据的。
6.count(
,1,id,字段)
A.count()是一个聚合函数,对于返回的结果集,一行行地判断,如B.果参数不是null,累计值就加1,否则不加,最后返回累计值。
C.count(*) mysql优化器遍历的最小的索引数
D.count(1) innoDB引擎遍历整张表,但不取值
E.count(id) innoDB引擎会遍历整个表,把每一行的id值都取出来,返回给server层。
F.count(字段) 取值,判断非Null,统计累积
count(字段)<count(id)<count(1)≈count(x)

7.order by 工作原理
7.1全字段排序
a. 排序步骤
1.初始化sort_buffer,确定放入name,city,age这三个字段
2.从索引city找到第一个满足city=杭州条件的主键id,
3.到主键id索引取出整行,取name,city,age三个字段的值,存入sort_buffer
4.从索引city取下一个记录的主键id
5.重复3,4直到city不满足条件为止
6.对sort_buffer中的数据按照字段name做快速排序
7.按照排序结果取前1000行返回给客户端
b. 影响排序的因素
1.sort_buffer_size
2.如果排序的数据量<=sort_buffer_size,则排序在内存中完成
3.如果排序的数据量>sort_buffer_size,需要额外利用磁盘临时文件
4. 12 份 number_of_tmp_files
5:mysql外部排序一般使用归并排序算法,将数据分成12份,每一个单独存入临时文件中,然后把12个有序文件再合并成一个有序的大文件
c:总:算法过程中,只对原表的数据读一遍,剩下的操作都在sort_buffer和临时文件中执行,如果查询的字段很多,内存里放的行很少,就得分成很多临时文件,排序性能会很差

7.2 rowid排序
a. max_length_for_sort_data,如果单行超过这个值,就会使用rowid算法
b. 排序步骤
1.初始化sort_buffer,确定放入name(排序规则),id
2.从索引city找到第一个满足city=杭州条件的主键id,
3.到主键id索引取出整行,取name,id的值,存入sort_buffer
4.从索引city取下一个记录的主键id
5.重复3,4直到city不满足条件为止
6.对sort_buffer中的数据按照字段name做快速排序
7.按照排序结果取前1000行,并按照id的值回到原表中取city,name,age三个字段返回给客户端

逻辑概念,不需要在服务端再消耗内存存储结果,是直接返回给客户端的
总:排序的总数据量变小了,所以需要用到的临时文件会变少了。
7.3 比较
a.mysql一般认为内存足够大,这样可以减少再次去磁盘中查询数据。所以不会优先选取rowid排序;
b.如果内存够,就要多利用内存,尽量减少磁盘访问
并不是所有的order by语句都需要排序操作,如果原有的查询结果就是有序的就不需要排序了。

8.如何正确显示随机数
8.1 order by rand()
使用内存临时表,内存临时表排序的时候使用了rowid的排序方法;
计算过程比较复杂,需要大量的扫描行数,因此排序过程的资源消耗也会很大
8.2 Extra- using temporary 使用临时表
8.3 Extra- using filesort 执行排序操作
8.4 随机排序方法
1.上线前可以剔除空洞
a.取表的主键Id的最大值M和最小值N
b.随机函数生成X=(M-N)rand()+N
c.取不小于X的第一行ID的行
2.取整个表的行数C;取得Y=floor(C
rand());再用limit Y,1取得一行

9.三种慢sql
9.1 条件字段函数操作
a. select *from t where month(t_modify)=7;
b. 对索引字段做函数操作,可能破坏索引值的有序性,因此优化器就决定放弃走树的搜索功能
c. 优化器并不是放弃索引,从explain结果看还是走了索引,全索引扫描。
d. 推荐: select *from t where t_modify>=‘2020-7-1’ and t_modify<‘2020-8-1’;
9.2 隐式类型转换
a. select * from t where tId =1111; tId为varchar(32)
b. 实际上优化器执行的语句时:select * from t where cast(tId as signed int) = 1111;
c. 实际原因还是触发了,对索引字段做了函数操作,优化器放弃走树搜索功能
9.3 隐式字符编码转换
a. 两个表的字符编码不一致,会导致隐式字符转换,出现索引字段函数操作,导致全索引扫描
b. select * from t where convert(tId using utf8mb4)=$L2.tId,value

10.查一行记录也很慢的sql
10.1 查询长时间不返回
a.等MDL锁:有一个线程正在表t上请求或持有MDL的写锁,把select语句堵住了;sys.schema_talbe_lock_waits找出阻塞线程,keill断开连接;
b.等flush : show processlist中可以看到 waiting for talbe flush
c. 等行锁 : sys.innodb_lock_waits查询行锁; select * from t sys.innodb_lock_waits where lock_talbe = ‘test.t’\G;
10.2 查询慢
a.无索引主键顺序扫描: select * from t where c=50000 limit 1;坏查询
b.扫描一行,执行很慢: select * from t where id=1[一致性读];select * from t where id=1 lock in share mode[当前读];
10.3 ex:
a. select * from t where b = ‘1234567890abcd’;
b. t表数据100w,b='1234567890’有10w行;b定义为varchar(10)
c. 执行过程:
1.在传给引擎执行的时候,做了字符截断。取前10个字符进去匹配
2.找到了10w行
3.select * ,所以要10w次回表
4.每次回表以后查出整行,到server层判断是否满足b=‘1234567890abcd’
5.返回空值

11.幻读
11.1 幻读是什么?
a.幻读是指一个事务在前后两次查询同一个范围的时候,后一次查询看到前一次查询没有看到的行
b.在可重复读的隔离级别下,普通的查询是快照读,是不会看到其他事务插入的数据的。因此,幻读在当前读才会出现
c. 幻读仅专指新插入的行
d.当前读: for update,能读取到所有已提交的记录的最新值。
11.2 幻读有什么问题?
a.破坏了行锁的语义;
b.出现了数据不一致
11.3 如何解决幻读?
a.行锁只能锁住行,无法防止新的插入,innoDB引入了间隙锁
b.6个记录,7个间隙;记录间和前后间隙
c.间隙锁 gap lock: 间隙锁没有锁冲突的概念,其目的是为了防止间隙中插入新的行;间隙锁+行锁 next-key lock
11.4 间隙锁和next-key lock解决了幻读问题,也可能造成死锁,可能会导致同样的语句锁住更大的范围,影响了并发度。

12.加锁规则
12.1.前提: 版本<5.7.24;<8.0.13;可重复读隔离级别
12.2.加锁规则
a.原则1:加锁的基本单位是next-key lock;next-key lock是前开后闭区间
b.原则2:查找过程中访问到的对象才会加锁
c.优化1:索引上的等值查询,为唯一索引加锁的时候,next_key lock退化为行锁
d.优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock退化为间隙锁
e.bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止
12.3 在删除数据的时候尽量加limit,不仅可以控制条数,让操作安全,还可以减少加锁的访问

13.mysql提高性能的方法
13.1 短连接风暴:正常的短连接模式是连接到数据库后,执行很少的SQL语句就断开,下次需要的时候再重连。业务高峰期会出现连接数突然暴涨的情况。如果超过max_connetions,数据库会报错,提示“too many connections”,从业务角度看就是数据库不可用。不能去临时调高max_connections这个值,因为这个值本身就是来保护mysql的,如果连接数增大,系统负载加大,大量资源耗费再权限验证等逻辑上,结果适得其反,可能导致已经连接的线程拿不到cpu去执行业务的sql请求。
解决1:先处理掉那些占着连接但是不工作的线程。先用show processlist查看那些sleep的线程,然后使用kill connections +id 处理这个连接,并告知业务。
解决2:减少连接过程的消耗。跳过权限验证:重启数据库,并使用-skip-grant-tables参数启动mysql。这样mysql会跳过所有的权限验证阶段,包括连接过程和语句执行过程在内。风险极高。
13.2 慢查询性能问题
1.索引没有设计好
2.sql语句没有写好
3.mysql选错索引
解决1:对于没有设计好的索引,我们可以用过紧急创建来解决。mysql5.6后支持online DDL了,如果业务高峰期数据库被这个语句打挂了,可以直接执行alter table语句。具体方案:step1.先在备库执行set sql_log_bin = off,也就是不写binlog,然后执行alter table增加索引;step2.执行主备切换;step3.在新的备库执行 set sql_log_bin = off,然后执行alter table语句加上索引。
解决2:sql语句没有写好,使用存储过程来“查询重写”
解决3:mysql选错索引,force index /查询重写
如何避免1和2:
1.上线前在测试环境,把慢查询日志(show log)打开,set long_query_time=0,确保每个语句都会写入慢查询日志。
2.在测试表中插入模拟线上的数据,做一遍回归测试。
3.观察慢查询日志里每类语句的输出,特别留意row_examined字段是否与预期一致。
4.推荐使用工具pt-query-digest
13.3 系统新功能bug导致QPS 突增的问题
解决1:干掉白名单;
解决2:删除单独的数据库用户
解决3:直接查询重写(select 1)替代之前的sql语句,风险极高,可能会误伤其他业务,也可能导致后续依赖的业务不可用。
1和2的解决方案都要依赖规范的运维体系:虚拟化,白名单机制,业务账号分离。

14.mysql是怎么保证数据不丢失的?
只要redo log和binlog保证持久化到磁盘,就能确保Mysql异常重启后,数据可以恢复。
14.1 bin log的写入机制:
事务执行过程中,先把日志写入binlog cache,事务提交的时候,再把binlog cache写到binlog文件中。每个线程都有一个binlog cahche ,但是公用一份binlog文件。
14.2 redo log的写入机制:
1.事务执行中,redo log先写入redo log buffer中,物理上在Mysql进程内存中。
2.再写到磁盘(write),但是没有持久化(fsync),物理上是在文件系统的page cache里面。
3.持久化到磁盘fsync
14.3 两阶段提交细化:
redo log prepate:wirte – 1
binlog:write – 2
redolog prepare:fsync-- 3
binlog:fsync --4
redo log conmit:write.–5
14.4 binlog是不能被打断的?
答:一个线程只能同时有一个事务在执行。如果一个事务的binlog被拆开的时候,在备库执行就会被当成多个事务分段执行,这样就破坏了原子性,是有问题的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值