11-Concurrency
Concurrency
事务的隔离级别
如果不考虑并发事务的隔离行,会造成以下问题:
- 脏读:读取到了其他事务未提交的数据(必须解决)
- 不可重复读:同一个事务两次读取到的数据不一致
- 幻读:同一个事务查询同一个已查询数据后发现不存在了
四种隔离级别
- READ UNCOMMITED-读未提交(作用不大,PGSQL也没有,这里只是为了完整性)
- READ COMMITED-读已提交(可以解决脏读,PGSQL默认隔离级别)
- READ REPEATABLE-可重复读写(可以解读脏读,不可重复读,MYSQL默认隔离级别)
- SERIALIZABLE-串行化(可以解决所有,锁,效率慢)
MVCC
MVCC(Multi-Version Concurrency Control) 是 MySQL 数据库用来处理并发访问的技术,特别是在 InnoDB 存储引擎中,MVCC 允许多个事务并发执行而不互相干扰,确保数据的一致性和隔离性。MVCC 通过为每个数据行维护多个版本来实现这一点,每个版本对应一个特定时间点的数据状态,从而允许读操作不被写操作阻塞,同时避免数据的冲突。
MVCC 的工作原理
在PGSQL中,每个表自带xmin,xmax两个字段
- xmin:给当前事务分配的数据版本。如果有其他事务做了写操作,并且提交事务了就给xmin分配新的版min :
- xmax:当前事务没有存在新版本,xmax就是0。如果有其他事务做了写操作,未提交事务,将写操作的版本放到xmax中。提交事务后,xmax会分配到xmin中,然后xmax归0。



MVCC 的优势
1. 提高并发性
- MVCC 允许多个事务同时读取和修改不同版本的数据行,显著提高了并发性能,尤其是在只读操作较多的场景中。读操作不会被写操作阻塞,写操作也不会影响未修改的数据行的读取。
2. 避免锁竞争
- 通过使用版本控制,MVCC 能够避免行级锁的竞争,减少了传统锁机制下的阻塞和性能瓶颈。在高并发环境下,尤其是在长事务中,MVCC 可以显著提高效率。
3. 实现一致性读
- 在 InnoDB 存储引擎中,MVCC 使得 一致性读 成为可能。即使有其他事务在修改数据,当一个事务读取数据时,它总是看到事务开始时的数据快照,而不是被其他事务修改的数据,这确保了数据的一致性。
MVCC 的挑战和限制
1. 内存和磁盘空间消耗
- 每次数据行修改时,都会创建一个新的版本。这可能导致存储空间的增加,尤其是当大量数据被修改时,多个版本会占用更多的内存和磁盘空间。
- 定期清理旧版本是必要的,这通常通过 垃圾回收(Garbage Collection) 来完成,InnoDB 会删除已经不再需要的版本。
2. 更新操作的开销
- 每次更新时,InnoDB 都需要创建新版本的数据行,并更新撤销日志。这可能会增加 I/O 操作的开销,特别是在数据更新频繁的情况下。
3. 脏读和幻读的可能性
- 在较低隔离级别(如 读未提交 或 读已提交)下,可能会出现 脏读(读取未提交的数据)或 幻读(在一个事务内重复读取数据时,结果集的内容发生变化)现象。为了避免这些问题,需要选择合适的事务隔离级别(如 可重复读 或 串行化)。
总结
MySQL 的 MVCC 通过版本控制和撤销日志来实现并发控制,允许多个事务同时执行而不互相干扰,提高了数据库的并发性能和隔离性。MVCC 是 InnoDB 存储引擎的核心特性之一,广泛应用于高并发场景中。然而,尽管 MVCC 提供了显著的性能优势,它也带来了一定的存储和内存消耗,并且需要合理配置以避免脏读和幻读等问题。
表锁
语法
LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
where lockmode is one of:
ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
begin; -- 需要先开启事务
lock table_index in access share mode; -- 读锁
lock table_index in access exclusive mode; -- 写锁
行锁
主要行锁类型
- 行级共享锁 (FOR SHARE)
- 允许其他事务读,但阻止其他事务获取独占锁
- 适用于读取数据并防止其他事务修改
- 行级排他锁 (FOR UPDATE)
- 阻止其他事务获取共享锁或排他锁
- 适用于需要修改数据的场景

浙公网安备 33010602011771号