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。

image-20260104210219954

image-20260104210641129

image-20260104210630779


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)
    • 阻止其他事务获取共享锁或排他锁
    • 适用于需要修改数据的场景
posted @ 2026-01-05 16:28  大胖熊哈  阅读(2)  评论(0)    收藏  举报