mysql的锁总结


表锁

行锁 :记录锁(record lock)、间隙锁(gap lock)、临间锁(next-key lock)。行锁是加在索引上的,没有索引是加不上行锁的

共享锁:又称读锁(lock in share mode),例如select,当上锁之后,另一个线程只可以读,不可以修改。
排他锁:又称写锁(for update),例如update,insert,delete,上锁之后,另一个线程不可以读和修改。

 

读锁(共享锁、S锁):多个事务同时读,不能写。
写锁(排他锁、互斥锁、X锁):一个事务能写能读,其他的事务都不行
mdl(meta data lock、元数据锁):查询事务一旦开始,不能修改表结构

意向锁:表锁,获取锁前先要获取意向锁,不能修改表结构。   
一、意向共享锁(IS) 是指在给一个数据行加共享锁前必须获取该表的意向共享锁。
二、意向排它锁(IX) 是指在给一个数据行加排他锁前必须获取该表的意向排他锁。

 

乐观锁:无锁   version来控制

悲观锁:mysql都是悲观锁  上锁

聚簇索引:每个节点含有主键 和 每个叶子结点包含表中所有数据。
非聚簇索引:只包含索引,先查非聚簇索引,然后回表查聚簇索引。

select for update :
主键索引:只对聚簇索引加锁,直接查聚簇索引。     
非主键索引:加两把锁,聚簇索引和非聚簇索引,先加锁普通索引(非聚簇索引),再加锁主键索引(聚簇索引)。 

select * from table where id = 1 
select * from table where id = 1 for update

SELECT 和 SELECT FOR UPDATE两个例子
 总结:写锁的RC解决不了幻读,就不需要间隙锁,RR解决了幻读,就需要间隙锁

mysql可重复读隔离(RR)级别不是可以通过间隙锁解决幻读么,为什么又说RR级别无法解决幻读?

因为不加for update的读是不加锁的,用的是MVCC快照读。加了for update就会加排他行锁和间隙锁,并在这次事务结束解锁。
MVCC 的局限性: MVCC 保证了快照读的一致性视图,但写操作(当前读)必须基于最新数据,否则会导致更新丢失或逻辑错误

  • 定义差异:SQL 标准中对幻读的定义更严格,要求所有数据变化(包括更新、删除)都不应该被当前事务看到。而 MySQL 的 RR 级别虽然解决了 “插入导致的幻读”,但对于更新和删除操作导致的幻读现象并未完全解决。
    • 示例(更新导致的幻读):
      sql
      -- 事务A
      BEGIN;
      SELECT * FROM users WHERE age > 20;  -- 假设返回10条记录
      
      -- 此时事务B执行:UPDATE users SET age = 25 WHERE id = 1;(id=1的用户原本age=19)
      SELECT * FROM users WHERE age > 20;  -- 可能返回11条记录(包含了被事务B更新的记录)
      COMMIT;
    • 这种情况下,事务 A 两次查询的结果集行数不一致,尽管 MySQL 的 MVCC 机制保证了行内容不变(即读到的同一行数据不会变化),但行数可能变化,因此从严格定义上讲,仍存在幻读。

 

ACID如何保证?

A.原子性

 C.持久性

 

 

Redo log

当我们想要修改DB上某一行数据的时候,
InnoDB是把数据从磁盘读取到内存的缓冲池上进行修改。数据在内存中被修改,与磁盘中相比就存在
了差异,我们称这种有差异的数据为脏页。InnoDB对脏页的处理不是每次生成脏页就将脏页刷新回磁
盘,这样会产生海量的IO操作,严重影响InnoDB的处理性能。

redo log的工作原理。说白了,redo log就是存储了数据被修改后的值。当我们
提交一个事务时,InnoDB会先去把要修改的数据写入日志,然后再去修改缓冲池里面的真正数据页。

 

I:隔离性

 

 

D:一致性:一些约束,唯一索引,错误检查器check一些字段

 

posted @ 2022-03-12 09:15  飘来荡去evo  阅读(75)  评论(0)    收藏  举报