MySql的MVCC_存储引擎_历史_开发模式

一. 多版本并发控制(MVCC)

1.概述

可以认为MVCC是行级锁的一个变种,其在很多情况下避免了加锁操作,因此开销更低

不同存储引擎的MVCC实现是不同的,但大部分实现了非阻塞的读操作,写操作也只锁定必要的行。

MVCC的实现,是通过保存数据在某个时间点的快照来实现的。即不管需要执行多长时间,每个事务看到的数据都是一致的

在这里插入图片描述

2.InnoDB的MVCC

  • 在每行记录后面保存两个隐藏的列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。
  • 注意存储的并不是实际的时间值,而是系统版本号(system version number)
  • 每开始一个新的事务,系统版本号都会自动递增
  • 事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较

REPEATABLE READ隔离级别下的MVCC
在这里插入图片描述
优点:

  • 保存这两个额外系统版本号,使大多数读操作都可以不用加锁。
  • 读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行

缺点:

  • 每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作

注意:

  • MVCC只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作。
  • 其他两个隔离级别都和MVCC不兼容:
    READ UNCOMMITTED总是读取最新的数据行,不是符合当前事务版本的数据行;而SERIALIZABLE则会对所有读取的行都加锁,mvcc不涉及锁的概念。

二.MySql的存储引擎

1.mysql概览

在这里插入图片描述
例如:SHOW TABLE STATUS命令,mysql数据库中的user表
在这里插入图片描述

2. InnoDB存储引擎

2.1 作用

在这里插入图片描述

2.2 历史

在这里插入图片描述

2.3 概览

在这里插入图片描述

3. MyISAM存储引擎

MySQL 5.1及之前的版本,MyISAM是默认的存储引擎

但MyISAM不支持事务和行级锁,而且有一个毫无疑问的缺陷就是崩溃后无法安全恢复

对于只读的数据,或者表比较小、可以忍受修复(repair)操作,可以继续使用MyISAM。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MVCC(Multi-Version Concurrency Control)是MySQL InnoDB存储引擎的一种并发控制机制,可以提高数据库的并发性能。下面是Java实现MVCC的大致思路: 1. 在Java中实现MVCC需要使用到数据库连接池,可以使用开源的c3p0或Druid连接池。 2. 在InnoDB存储引擎中,每行数据都有一个隐藏的6字节的事务ID(即版本号),表示该行数据的版本号。在Java中,可以使用一个类来表示这个版本号,比如: ```java public class TxnId { private int trxId; // 事务ID private int rollPointer; // 回滚指针 // 省略get、set方法 } ``` 3. 当一个事务开始时,需要从连接池中获取一个数据库连接,并设置该连接的事务隔离级别为可重复读(Repeatable Read)。在Java中,可以使用JDBC来设置事务隔离级别。 ```java try { Connection conn = pool.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); conn.setAutoCommit(false); // 执行一些SQL语句 conn.commit(); } catch (Exception e) { // 异常处理 } ``` 4. 当从数据库中读取数据时,需要读取该数据的最新版本。如果该数据的版本号比当前事务的版本号旧,说明该数据已经被其他事务修改过了,当前事务不能读取该数据。在Java中,可以使用SELECT ... FOR UPDATE语句来实现这个功能。 ```java try { Connection conn = pool.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); conn.setAutoCommit(false); String sql = "SELECT * FROM table WHERE id = ? FOR UPDATE"; PreparedStatement ps = conn.prepareStatement(sql); ps.setInt(1, id); ResultSet rs = ps.executeQuery(); if (rs.next()) { // 读取数据 } conn.commit(); } catch (Exception e) { // 异常处理 } ``` 5. 当向数据库中插入、更新、删除数据时,需要生成一个新的版本号,并将该版本号保存到数据中。在Java中,可以使用UPDATE ... SET语句来实现这个功能,例如: ```java try { Connection conn = pool.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); conn.setAutoCommit(false); int newTrxId = getNextTrxId(); String sql = "UPDATE table SET value = ?, trx_id = ? WHERE id = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, value); ps.setInt(2, newTrxId); ps.setInt(3, id); int rows = ps.executeUpdate(); if (rows == 1) { // 更新成功 } conn.commit(); } catch (Exception e) { // 异常处理 } ``` 6. 当事务提交时,需要将该事务的版本号保存到事务ID列表中。在Java中,可以使用一个列表来保存事务ID,例如: ```java public class TxnIdList { private List<TxnId> txnIds = new ArrayList<>(); // 添加事务ID public void addTxnId(TxnId txnId) { txnIds.add(txnId); } // 删除事务ID public void removeTxnId(TxnId txnId) { txnIds.remove(txnId); } // 判断事务是否已提交 public boolean isCommitted(TxnId txnId) { for (TxnId id : txnIds) { if (id.getTrxId() == txnId.getTrxId() && id.getRollPointer() != txnId.getRollPointer()) { return true; } } return false; } } ``` 7. 当事务回滚时,需要根据回滚指针来回滚数据。在Java中,可以使用ROLLBACK语句来回滚事务,例如: ```java try { Connection conn = pool.getConnection(); conn.rollback(); } catch (Exception e) { // 异常处理 } ``` 这样,就可以在Java中实现MVCC机制了。当然,这里只是一个简单的示例,实际上还有很多细节需要考虑,比如事务的隔离级别、事务的提交和回滚、事务ID的生成等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小骄傲_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值