闲话MVCC

为什么需要事务

其实和我们需要是一个道理。因为我们业务上的一个逻辑操作单元Tx_A,对应的是多个计算机指令。我们需要一种机制来确保在Tx_A操作执行期间,其内部状态不可以被外界观测到。如果外界访问,要么阻塞等待直到该操作结束。要么直接返回告诉它,“Sorry ,I’m busy now”。事务就是这样一种机制。做数据库的大神说,“得了,您也别自己去实现这样一种机制了,就我实现得了。你们会用就行,免得一大堆bug”,所以事务的出现使得我们能更好focus在我们的业务上。而不用自己去实现事务等价一套APIs。
事务是一个说明性的概念,这个概念用来表述你想要达到什么样的效果。

Mysql对外暴露的事务APIs如下:

  • 1.事务的开始
    • START TRANSACTION
    • BEGIN
  • 2.事务提交
    • COMMIT
  • 3.事务回滚
    • ROLLBACK

ANSI/ISO isolation(隔离级别)

一言以蔽之,隔离级别是事务之间可见性的定义。

1. 可序列化(Serializable)

可序列化涉及到范围锁(主要是用于解决聚集查询),所以没有幻读问题。

2.可重复读(READ-REPEATABLE)

在可重复读取(REPEATABLE READS)级别下,数据库系统会在整个事务期间保持读取锁写入锁。但相较于可序列化,范围锁不会持有,所以幻读可能会出现。

Ps:MySQL的MVCC兼容此隔离级别,并且避免了幻读问题。

3.不可重复读(READ-COMMITTED)

在READ COMMITTED级别下,整个事务期间保持写入锁,但读取锁会在SELECT执行之后立即释放。所以也称为NON-REPEATABLE READ。

4.读未提交(READ-UNCOMMITED)

在此隔离级别下,脏读可能会出现。
Ps:此处需要注意脏读含义的理解。
事务A如果可以看见其它事务的中间状态,那么就是脏读。换句话说,一个事务能看见的数据,要么在其它事务开始之前,要么是之后。事务是将数据库状态从某个一致的状态,变成另一种一致的状态。

小结

以MySql为例,大多数应用采用的隔离级别为REPEATABLE READ,所以SELECT读到的数据可能不是目前最新的(可见性?)。其实对大多数业务来说都OK,因为大多数业务并不要求全局的happen-before关系,而只要求某几个操作之间有。

MVCC

以隔离级别「READ-REPEATABLE」为例,按照上面「读写锁」的实现,那么读写依然是冲突的,能不能达到读写也不冲突呢?毕竟人类对性能的追求是无止境的。答案是肯定的。其思想上和Java的CopyOnWriteArrayList极为类似。简单来说
就是通过”volatile+写锁”实现。这样就可以实现
读写不互斥(通过volatile);
还是以经典的Bob给Simith转账100刀为例.

事务A
start
update account set balance=balance where id=’bob’ and balance >=100
commit;
事务B
start;
select balance where id=’bob’
commit;
现在假设事务A和事务B并行执行,照例说事务B,应该会等事务A提交时候( 提交会释放锁),之后才会读到bob账户余额,事实上由于读余额时,并不会尝试获取写锁,所以无需等待。所以读写不互斥。
Ps:肯定有同学会疑惑,这样不就是读得不是最新的了嘛?的确,这样读到的数据不是最新的,但是为什么需要读到最新的呢,对大多读事务场景,并不需要读到最新值啊,如果是写事务的话,那么对业务属性是否满足更新条件,必须放在update的where子句中,而不能先select后update,当然,对大多数应用,先selelct 如果(不)满足,然后(不)更新,如果大多数条件都不用更新,那么这么写,可能会有性能优化,毕竟select 无锁,update可是必须要锁的。

显示锁

隐式锁

  • select 隐式获取与释放读锁

写时复制(COW(Copy-On-Write))的

参考资料

PostgreSQL的MVCC(多版本并发控制)是一种用于支持事务并维持数据一致性的同时,允许并发读写的机制。这种技术在数据库管理系统中非常关键,尤其是在处理事务性和并发操作时。 ### MVCC的工作原理 #### 时间戳隔离 在MVCC中,每一行数据都有一个称为“时间戳”的版本标识符。当一个事务开始时,它会获取一个时间点作为其活动的开始,这个时间点包含了所有已提交事务的时间戳信息。事务在其整个生命周期内,只能够访问和修改那些在这个时间点前或同时创建的数据。 #### 数据行和快照 在MVCC中,数据行不是直接存储其原始值,而是包含了一个额外的版本信息。每个查询或操作都会从数据库中加载一组所谓的“快照”,即特定时刻的所有活跃事务的状态。这些快照由一系列的版本(版本树)组成,其中每个节点表示一个事务的更新状态。 #### 写入与删除 写入操作会在现有数据上建立一个新的版本,并将旧版本标记为历史记录。如果需要,可以保留多个历史版本供日志和恢复使用。删除操作实际上是修改数据的一次写操作,将其标记为不可见而非物理删除,以便于保持查询性能。 ### 相关优势 1. **高并发性**:通过限制事务对数据的访问范围,使得多个事务可以在同一时间内运行而不相互干扰。 2. **冲突解决**:自动管理并发操作带来的冲突,减少了应用开发者在并发处理上的复杂度。 3. **安全性**:避免了死锁和其他并发问题,提高了系统的稳定性和可靠性。 4. **性能优化**:通过避免全表扫描等低效操作,提高查询效率。 ### 使用场景及限制 1. **多用户环境**:在大量并发用户同时请求的情况下,MVCC能有效减少锁定等待时间和提高系统吞吐量。 2. **数据完整性**:确保在高负载下仍能满足ACID(原子性、一致性、隔离性、持久性)属性的需求。 3. **复杂查询**:支持复杂的SQL查询,包括JOIN操作,而不会因为并发读写引起的问题。 然而,尽管有上述优点,MVCC也有其局限性: - 需要更多的磁盘空间来存储额外的版本数据。 - 对一些特殊的查询或需求可能不如其他并发控制策略高效。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值