MYSQL系列3-如何处理数据更新

文章详细介绍了数据库在更新时产生的三种日志——binlog用于主从复制,redolog确保数据持久化,undolog保证原子性和隔离性。还探讨了MySQL的锁机制,包括全局锁、表级锁、行锁以及不同类型的读写锁,并解释了Next-KeyLock的工作原理。此外,文章还阐述了多版本并发控制(MVCC)的概念及其在MySQL中的实现。
摘要由CSDN通过智能技术生成
  1. 数据库的日志

  • 数据库在更新时,会产生binlog、redo log、undo log。

  • binlog,

  • server层产生的逻辑日志(主从复制时使用)。

  • redo log

  • InnoDB引擎产生的物理日志,保证持久化,ACID中的D(崩溃修复用日志)。

  • InnoDB“日志优先与数据”,记录redo log视为数据已更新。

  • 当数据写入磁盘后,redo log删除。

  • redo log存储在4个1GB的文件中,并且循环写入。

  • write pos是当前日志写入点。

  • check point是擦除点,数据更新到硬盘时被擦除。

  • 当write pos追上check point时,事务无法提交,需要等待check point推进。

  • 只要redo log不丢失,数据就不会丢失。

  • undo log

  • InnoDB引擎产生的逻辑日志,保证原子性、隔离性(例如:事务回滚,快照读)。

  • 位于表空间中的undo segment中。

  1. 客户端之间的影响

  • 客户端执行SQL时,会产生各种行锁、表锁、元数据锁。

  • 一个客户端产生的锁,会干扰其他客户端SQL语句的执行。

  • 两个客户端之间可能产生死锁。

  • 事务可能会产生隐式的锁,造成性能问题。

  1. MYSQL锁的种类

  • 按照粒度分,MYSQL的锁可以分为全局锁、表级锁、行锁。

  • 全局锁,锁住所有表,整个库无法修改,只能读取。

  • 表级锁,又可以分为表锁(数据锁)元数据锁(metadata lock)

  • 行锁,会锁住数据行,分为共享锁独占锁

  1. MYSQL-全局锁

  • FTWRL(Flush tables with read lock)。

  • 此命令使整个库处于只读状态。

  • 主要用途保证备份的一致性。

  • 不要随意使用,杀伤性极大,建议在备库使用。

  1. MYSQL-表锁(数据锁)

  • 命令:lock tables xxx read/write。

  • 上读锁后其他人不能改,上了写锁后其他人即不能读又不能写。

  • 表锁是非常重的锁,在InnoDB中很少用。

  1. MYSQL-元数据锁(metadata lock)

  • 元数据指的是表的结构、字段、数据类型、索引等。

  • 事务访问元数据时,会自动给表增加MDL读锁。

  • 事务修改元数据时,会自动给表增加MDL写锁。

  1. MYSQL-行锁

  • 行锁有两种类型,有很多种叫法,其实都是一回事

  • 读锁/写锁。

  • 共享锁/排他锁。

  • 共享锁/独占锁。

  • S锁/X锁。

  • 以读锁/写锁为例

  • 读锁

  • 自己要读,别人不可以写。

  • 写锁

  • 自己要写,不允许别人读和写。

  • 只有读锁和读锁可以兼容(重复上锁),其他均不兼容。

  1. MYSQL-Next-Key Lock

Next-Key实际上是通过间隙锁和行锁共同实现的一种加锁方式,只在可重复读(repeatable read)隔离级别下生效。

  • next可以理解为间隙,Key为行锁。

  • 加锁时以Next-Key为基本单位进行加锁。

  • 实例表结构

  • 唯一索引-等值查询间隙锁锁(被查询值不存在时)

  • 因为11不存在所以仅需要锁住(10,20)这个间隙。

  • 当11存在时仅锁住11这一条记录,因为时唯一索引。

  • 非唯一索引-等值锁(被查询值存在时)

  • Tx A事务语句,不涉及回表,走的是索引覆盖。因此Tx B事务可以对id=20这条记录加写锁(加在主索引上)。但是在执行插入(12,12,12)是会被阻塞,原因是辅助索引C已经被Tx A增加了间隙读锁。

  • 主键索引-范围锁(前后范围都存在)

  • Tx A执行后会锁住[20,30]。如果Tx B执行的是下图的查询语句会被阻塞。如果Tx B执行的是下图的插入语句则成功。

  • 非索引字段查询

  • 非唯一索引-范围锁(前后范围都存在)

  1. MYSQL-MVCC(多版本并发控制)

通过undo log来实现,MYSQL每次开启一个事务时会生成一个事务id,并且该id是自增的。同时undo log上的所有修改操作都会记录对应的事务id。

  • 补充两个读取的方式

  • 快照读

将数据库在过去某个时刻的快照应用在查询上,使得:这次查询只能看到别的事务生成快照前提交的数据。

例如:以上图为例子,一个查询事务,事务id为160,处于158与190之间。如果采用快照读的方式只能读取到比160事务id小的并且是已经提交的数据。

  • 当前读

每次查询最新的已经提交的数据。采用当前读的方式有,select ... for update、update、insert、delete操作。

来源:https://coding.imooc.com/learn/list/515.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值