只说innodb存储引擎
1. 默认使用行级锁
InnoDB 存储引擎默认使用行级锁定(Row-Level Locking)来提高并发性能和数据一致性
不可更改
2. 四种事务隔离级别,默认是Repeatable级别(可重复读)
问题场景:
- 脏读
1.A进行了一条数据操作,但是没有提交事务,如果此时B进行这条数据的查询,是可以查到A的数据操作结果的。
2.后来A还没有提交事务,反而不提交了或者进行了事务回滚,那么B查询到的数据就是脏数据。
- 不可重复读(侧重于修改)
事务A多次读取到同一个数据,而B在A多次读取的过程中,对数据进行了修改,导致事务A多次多去同一个数据的时候,结果不一致。
- 幻读(侧重于增加或者删除)
再一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多或者少的那一行数据叫做幻行。
事务隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题,下面展示了 4 种隔离级别对这三个问题的解决程度。
隔离级别 脏读 可重复读 幻读
读未提交 可能 可能 可能
读提交 不可能 可能 可能
可重复读 不可能 不可能 可能
串行化 不可能 不可能 不可能
从上往下,隔离强度逐渐增强,性能逐渐变差。采用哪种隔离级别要根据系统需求权衡决定
解决原理:
可重复读
读锁和写锁会持有到事务结束,但是不加范围锁。可重复度解决的问题是不可重复读
,不能解决的问题是幻读
。
读已提交
写锁会持有到事务结束,读锁在查询之后就会释放掉,没有范围锁。它解决的问题是脏读
,不能解决的问题是不可重复读
举例:可重复读是如何解决不可重复读问题的?
可重RR隔离级别下,分为快照读和当前读,快照读不加锁,锁定已存在的行
当前读 读锁和写锁会持有到事务结束(全程加锁),但是不加范围锁。此时可以解决不可重复度,但存在幻读
幻读问题:因为默认是行级锁,锁上的行不可修改,但表中可能会insert数据,(快照读只锁定已存在的行,而不锁定可能插入的新行)
当使用如:select count(*) from t_student where age < 20 查询时,发生幻读
其他知识:
mysql中InnoDB支持下面的几种锁
- 共享锁和排他锁(s锁和x锁)
- 意向锁
- 记录锁
- 范围锁(gap锁)
- next-key锁
- 插入意向锁
- auto-inc锁
- 专门给空间索引锁
这些锁都是InnoDB中支持的,也不是本文的重点,现代数据库基本提供了下面的三种类型锁
-
写锁(独占锁)
持有写锁,持有写锁的事务才可以对数据操作,数据有写锁的时候,别的事务不能写入数据,也不能添加读锁。
-
读锁(共享锁)
共享锁,持有读锁的事务可以同时访问数据(数据可以持有多个读锁),数据添加读锁之后不能再添加写锁(读写互斥)。对于持有读锁的数据,如果只有一个事务,读锁是可以升级为写锁,写入数据。
-
范围锁
对于某个范围直接添加排他锁,在这个范围里面的数据是不能被写入的。比如:
select * from t_student where age > 12 and age < 30 for update
设置隔离级别:
-- 设置当前会话的隔离级别为可重复读
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- 设置全局的隔离级别为读已提交
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
LEVEL 可选 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 或 SERIALIZABLE
3.
快照读(Snapshot Read)
- 定义:快照读是指事务读取的是某个时间点的一致性视图(快照),而不是最新的数据。
- 特点:
- 读取的是事务开始时或某个特定时间点的数据快照。
- 不会对读取的数据加锁,因此不会阻塞其他事务的读写操作。
- 主要在
REPEATABLE READ
和READ COMMITTED
隔离级别下使用。
- 实现:InnoDB 使用多版本并发控制(MVCC)来实现快照读。每个事务在开始时会获得一个事务ID(transaction ID),并根据这个ID读取相应版本的数据。
- 示例:
sql
深色版本
SELECT * FROM orders WHERE customer_id = 100;
当前读(Current Read)
- 定义:当前读是指事务读取的是最新的数据,而不是某个时间点的快照。
- 特点:
- 读取的是最新的、已提交的数据。
- 会对读取的数据加锁,以防止其他事务修改这些数据。
- 主要在
REPEATABLE READ
和SERIALIZABLE
隔离级别下使用。
- 实现:InnoDB 使用锁机制来实现当前读。常见的当前读操作包括
SELECT ... FOR UPDATE
、SELECT ... LOCK IN SHARE MODE
、INSERT
、UPDATE
和DELETE
。 - 示例:
sql
深色版本
SELECT * FROM orders WHERE customer_id = 100 FOR UPDATE;
区别
-
读取的数据版本:
- 快照读:读取的是事务开始时或某个特定时间点的数据快照。
- 当前读:读取的是最新的、已提交的数据。
-
锁机制:
- 快照读:不加锁,允许多个事务并发读取同一数据。
- 当前读:加锁,防止其他事务修改正在读取的数据。
-
并发性能:
- 快照读:并发性能较高,因为不加锁,允许多个事务并发读取。
- 当前读:并发性能较低,因为加锁会阻塞其他事务的读写操作。
-
适用场景:
- 快照读:适用于需要读取历史数据或一致性视图的场景,如报表生成、数据分析等。
- 当前读:适用于需要读取最新数据并进行修改的场景,如库存管理、银行转账等
标签:行级,事务,快照,读取,读锁,mysql,数据,四种,隔离 From: https://www.cnblogs.com/light-LifeClub/p/18498229