mysql笔记-锁介绍

学习资料:关于MySQL内核,一定要知道的!

并发控制

并发控制保证数据一致性的方法:

(1)锁:

  普通锁:串行执行

  读写锁:读读并发

(2)数据多版本: 读写并发

  (1)写任务发生时,将数据克隆一份,以版本号区别 ;

  (2)写任务操作新克隆的数据,直至提交

  (3)并发读任务可以继续读旧版本的数据,不至于阻塞

实现读取旧版本数据:

  redo日志:redo日志存储已提交的数据,用于保障已提交数据的ACID特性。

    1.当数据库对数据做修改的时候,需要把数据页从磁盘读到buffer pool中,然后在buffer pool中进行修改,那么这个时候buffer pool中的数据页就与磁盘上的数据页内容不一致,称buffer pool的数据页为dirty page 脏数据,如果这个时候发生非正常的DB服务重启,那么这些数据还没在内存,并没有同步到磁盘文件中(注意,同步到磁盘文件是个随机IO),也就是会发生数据丢失。把相应修改记录记录到redo文件中(顺序IO),恢复DB时,根据redo文件的记录内容,重新刷到磁盘文件上,数据保持一致。

    2.如果每次都将事务提交的数据更新随机写到磁盘上,性能较低。优化:将修改数据顺序写到redo日志里,定期刷到磁盘上。

  undo日志:undo日志存放数据被修改前的值,保障未提交数据对数据库ACID特性产生影响。

    事务未提交前,将修改数据的镜像(修改前的旧版本),当事务回滚或者数据库崩溃时,恢复旧版本。

    insert行为undo日志存PK,update/delete行为undo日志存row。分别存在不同的buffer里。

  回滚段:存储undo日志

InnorDB如何做到高并发:InnorDB是基于多版本并发控制(MVCC)的存储引擎

  回滚段里的数据是历史数据的快照,快照读(不加锁一致性读)是innorDB如此高并发的原因。

  普通的select都是快照读,除非显示加锁,如select .. fro update 。

快照读读取到的数据版本与什么有关?

  RC(读提交)下,快照读总是读取到最新的行数据快照(已提交的事务)

  RR(可重复读)下,读取首次read的数据版本,与并发事务的开始时间、互斥关系(不加锁)无关。假设首次read的时间记为T,不会读取T时间后提交的记录。

1.七种锁

1) 自增锁:

  是特殊的表级别锁,针对事务插入AUTO_INCREMENT列。如果一个事务在插入,其他事务必须等待。

2)共享/排它锁

  共享锁S:读锁

  排它锁X:写锁。很强的锁,不与其它锁兼容。

  读读可以并行,读写、写写互斥。

3)意向锁

  意向锁是在事务要加共享/排它锁之前先做的一个意向声明。是一个表级别的锁。

  意向共享锁IS:事务有意向向表中某些行加共享s锁

  意向排它锁IS:事务有意向向表中某些行加排它x锁

 4)插入意向锁

  专门针对insert操作。多个事务,在同一个索引,同一个范围,如果插入位置不冲突,不会阻塞彼此。

5)记录锁

  封锁索引记录。比如:select ... for update

6)间隙锁

  封锁索引记录的间隔。防止其他事务在间隔中插入数据。比如:select .. betweend ... and .. for update

7) 临键锁

  封锁索引记录和索引区间。防止幻读。

 

乐观锁和悲观锁。乐观锁使用版本号,悲观锁是一直等待;

表锁:

lock table 

行锁:

begin 开启事务

sql

commit 提交事务

2.事务

1)四个特性:

A原子性:事务里所有操作要么全部都执行,要么全不执行

C一致性:所有操作全部成功或全部失败

I隔离性:事务中间处理过程对外不可见

D永久性:数据修改是永久的

2)并发事务带来的问题:

更新丢失:乐观锁使用版本号,低版本的更新会丢弃

脏读:事务A读到了事务B修改但未提交的内容

不可重复读:事务A读到事务B修改已提交的内容。举例:事务A第一次来查询,做了后续的业务处理,事务B进行数据修改的提交,事务A再次来查询,此时数据的修改可能会影响事务A的业务逻辑判断。

幻读:事务A读到了事务B提交的更新数据。举例:事务A第一次查询只有三条数据需要修改,事务B进行新增数据的提交,最终更新了四条数据。

3)事务隔离级别:mysql默认的隔离级别是Repeated Read(RR)可重复读

查看事务隔离级别:show variables like 'tx_isolation' 

隔离级别 脏读  不可重复读 幻读
读未提交
读已提交
可重复读
可串行化

 

可重复读的mvcc机制:

select操作不会更新版本号,是快照读(历史版本)

insert、update、delete 会更新版本号,可查询到其他事务提交的修改(即会出现幻读)

4)优化建议:

1.尽可能让所有数据检索通过索引完成,避免无索引行锁升级为表锁

2.尽可能检索条件避免间隙锁

3.尽可能控制事务大小,减少锁定资源量和时间长度

4.尽可能低级别事务隔离

3.实例

各种sql加了什么锁

 

posted @ 2020-04-16 21:40  hy叶子  阅读(163)  评论(0编辑  收藏  举报