MySQL

InnoDB vs MyISAM

  • InnoDB是聚簇索引(叶子节点存数据),MyISAM是非聚簇索引(叶子节点存指针)
  • MyISAM不支持事务,不支持外键
  • MyISAM只支持表锁,不支持行锁
  • MyISAM支持全文检索

日志

  • MySQL 日志:bin log
  • InnoDB 日志:redo log,undo log

主从复制

  • 主:binlog dump线程 - SQL更新语句记录在binlog
  • 从:io线程 - 拉取master的binlog,写入自己的relay log
  • 从:SQL执行线程 - 执行relay log里的语句

基于SQL语句的复制:binlog小,但是有些语句无法被复制,存储过程,触发器
基于行的复制:可靠性高,任何情况都可以复制,binlog大
混合复制:两种方式都可以用

bin log vs redo log

  • bin log 是逻辑的,SQL语句或记录行;redo log是物理的,对页的修改
  • redo log 操作是幂等性,bin log 不是
  • bin log 在事务提交时一次性写入;一个一个事务,顺序写入;
  • redo log 可以写多次到 redo log buffer,提交时写入日志;并发写入,不同事务的多个操作会混合写入

事务提交时,先写 bin log,再写 redo log
将事务放入队列,第一个事务称为leader,其他事务称为follower。分成3个阶段:flush/sync/commit
fulsh阶段:先写bin log内存,再写redo log内存。flush等待一段时间之后才进入sync
sync阶段:bin log刷盘,可能刷一个事务也可能刷多个事务
commit阶段:leader根据顺序提交事务,可以使用innodb的group commit

  • 事务提交 会刷日志文件(bin log + redo log),但不会刷数据文件
  • checkpoint 会同时刷日志文件和数据文件,使其有相同的 LSN (Log Sequence Number)
  • 主线程 每秒会刷日志文件(redo log)

redo log

  • redo log 有两部分:内存中的 redo log buffer,磁盘里的 redo log file
  • redo log block 大小为 512 字节,不需要 double write
  • 先写 redo log buffer(用户空间),再写 os buffer(内核空间),然后 fsync 到磁盘
  • innodb_flush_log_at_trx_commit: 0 事务提交时不进行写入操作,1 事务提交时必须调用一次fsync, 2 事务提交时仅写入文件系统的缓存,不进行fsync

undo log

  • 不是物理日志,是逻辑日志,存放在 共享表空间 的 undo段 (undo segment)
  • 共享表空间中有N个回滚段 rollback segment, 有 1024个 undo log segment
  • undo log 里存放的是记录,不是SQL语句
  • 逻辑的回滚到原来的状态,但是物理页已经修改了
  • insert undo log 在事务提交后直接删除,不需要进行purge操作
  • update undo log 提交时放入undo log链表,等待purge线程进行最后的删除

提升性能的关键特性

  • 插入缓冲
  • 两次写
  • 自适应哈希索引

插入缓冲 insert buffer

  • 解决非聚簇索引的随机插入的性能问题,非唯一索引
  • 先判断索引页是否在缓存中
  • 如果不在则放入插入缓冲区
  • 每隔一段时间执行插入缓冲区和非聚簇索引页的合并操作
  • Insert Buffer 是一棵B+树,存放在共享表空间

两次写 double write

  • 提高写的安全性,解决数据丢失(写失效)问题:16K的页只写了4K
  • 两个部分:内存里 double write buffer (2MB),磁盘上 共享表空间 (连续 128页 2MB)
  • 先把脏页拷贝到内存的doublewrite buffer
  • 分两次,每次写1MB到共享表空间,然后同步磁盘。此时是顺序写
  • 然后再写入各个 表空间,此时是随机写
  • 恢复过程,从 共享表空间 找到副页,然后写入 表空间

自适应哈希索引 Adaptive Hash Index

  • 只能用于等值的查询
  • 根据数据的访问频率和模式,热点数据
  • 通过缓冲池的B+树来创建自适应哈希索引,不用查磁盘上的索引页,所以很快

索引

  • 索引页:16K,留出1/16空闲页用于update/insert
  • 聚集索引按照主键顺序插入
  • 二级索引随机插入:先检查索引页是否在内存中,如果不在内存中则插入insert buffer,每隔一段时间合并属于同一个索引页
  • 自适应哈希索引:为经常被访问的索引页建立自适应哈希索引

MySQL事务

事务的ACID属性

  • Atomicity原子性:全部执行或者全部不执行
  • Consistency一致性:开始和完成时,数据保持一致性
  • Isolation隔离性:独立执行
  • Durability持久性:数据的修改是永久性的

ACID实现

  • 事务的ACID是通过日志和锁来保证
  • 隔离性是通过锁机制来实现
  • 持久性通过redo log来实现
  • 原子性和一致性通过undo log来实现

InnoDB通过 Force Log At Commit 来实现 持久性:commit时,必须将事务的所有日志写入redo log

事务回滚,通过undo log,insert 对应 delete, update 对应反向的 update来实现原子性

MVCC的实现就是靠undo log,通过undo读取之前的行版本信息: RR隔离级别下,总是读事务开始的行数据;RC隔离级别下,总是读最新的快照

并发事务处理的问题

  • 脏读:一个事务查询了另一个事务未提交的数据更新
  • 不可重复读:一个事务重新查询,发现了另一个事务更新的数据
  • 幻读:一个事务重新查询,发现了另一个事务插入的数据
  • 更新丢失:一个事务覆盖了另一个事务的数据更新

事务隔离级别(读数据一致性):

  • 读未提交 read uncommited:脏读,不可重复读,幻读
  • 读已提交 read commited:不可重复读,幻读
  • 可重复读 repeatable read:幻读
  • 串行化 serializable

MySQL MVCC 多版本并发控制

  • 记录增加两个隐藏列,创建事务版本号,删除事务版本号。
  • 更新的时候删除旧记录,创建新记录。
  • 查询的时候需满足:
    • 创建版本号小于等于事务版本号
    • 删除版本号大于事务版本号

Spring事务的传播行为

传播行为 说明
PROPAGATION_REQUIRED 默认值。如果没有则新建事务,如果有则加入当前事务
PROPAGATION_REQUIRES_NEW 如果没有则新建事务,如果有则挂起当前事务
PROPAGATION_NESTED 如果没有则新建事务,如果有则新建当前事务的子事务
PROPAGATION_SUPPORTS 如果没有则非事务,如果有则加入当前事务
PROPAGATION_NOT_SUPPORTED 如果没有则非事务,如果有则挂起当前事务
PROPAGATION_NEVER 如果没有则非事务,如果有则抛出异常
PROPAGATION_MANDATORY 如果没有则抛出异常,如果有则加入当前事务

InnoDB锁机制

乐观锁

读取数据的时候不加锁,更新数据的时候会判断数据是否被修改。
一般通过版本号或CAS实现。

悲观锁

读取数据的时候会加锁。
表锁,行锁,共享锁,排他锁,都是悲观锁

表锁

  • 意向共享锁IS:事务给一个数据行加共享锁之前必须先取得该表的意向共享锁
  • 意向排他锁IX:事务给一个数据行加排他锁之前必须先取得该表的意向排他锁

行锁 Row Lock

  • 共享锁S:允许事务去读一行,阻止其他事务获取该数据集的排他锁
  • 排他锁X:允许事务更新数据,阻止其他事务获取该数据集的共享读锁与排他写锁

要点:行锁通过给索引项加锁实现,而不是给记录加锁。只有通过索引检索才使用行锁,否则使用表锁。

INSERT,UPDATE,DELETE语句自动加排他锁。

SELECT语句需要手动加锁:

  • 共享锁:SELECT ... LOCK IN SHARE MODE
  • 排他锁:SELECT ... FOR UPDATE

间隙锁 Gap Lock

  • 使用范围条件检索,不存在的记录也会被加锁
  • 使用相等条件检索也会给不存在的记录加锁
  • 能够将左右两边不存在的记录加锁:SELECT MAX(...) ... FOR UPDATE

要点1:唯一索引只有行锁,非唯一索引才有间隙锁
要点2:间隙锁锁住了左边和右边不存在的记录,比如{2, 4, 6},如果查询条件是4,那么间隙锁锁住的是左边[3, 4),右边[5,6)

Next-Key Lock

  • 非唯一索引,包含行锁和间隙锁,用于防止幻读
  • 唯一索引,降级为行锁

InnoDB会加Netx-Key Lock,包括行锁(Record Lock)和间隙锁(Gap Lock)。间隙锁会锁住后面没有的记录,可以用来解决幻读的问题。比如事务A一开始使用select ... for update读出3条记录,此时由于间隙锁的存在,事务B将不能插入ID为4的记录,所以就不存在幻读的问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 我们都知道事务有4种特性:原子性、一致性、隔离性和持久性,在事务中的操作,要么全部执行,要么全部不做,这就是事务的...
    pjmike阅读 31,761评论 5 36
  • 这篇文章主要涉及到MySQL的知识点: 索引(包括分类及优化方式,失效条件,底层结构) sql语法(join,un...
    一根薯条阅读 2,695评论 0 8
  • 写在前面 本文是对于网上各个对redo和undo log日志解析的总结,参考文章列表在最后。 事务的4大特性:原子...
    吕信阅读 8,144评论 0 11
  • 数据库概念 锁分类 锁(按照锁粒度分类) 表级锁:每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发...
    尘世的鱼阅读 789评论 1 8
  • 一、事务概述 我们可以将事务理解为一组sql语句的集合。事务可以只包含一条sql,也可以包含多条sql,事务中所有...
    国球乒乓阅读 357评论 0 0