Mysql MVCC 原理 low_limit_id ReadView

  • 参考:感觉好多地方写的都不对。。还是看源码吧
  • MVCC Multi-version Concurrency Control
    • 怎么个MultiVersion法?
      • 每个开启的事务,会有一个tx_id,是不断自增长的,后面开的事务比前面开的事务大
      • 在默认的隔离级别:RepeatableRead,可重复读,需要做成,在事务中,看不到别人的修改,怎么做到呢?
        • 先引入一个概念:ReadView。ReadView里包含:
          • 当前活跃的事务id列表
          • 创建者的事务id
          • up_limit_id , low_limit_id 上下限,小于up_limit_id 可见, 大于low_limit_id 不可见。
            • 那么这个两个值是怎么赋值的呢。
            • low_limit_id 是系统最大的事务id值。up_limit_id是活跃事务列表的最小事务id
              • /* No future transactions should be visible in the view */
              • 349  view->low_limit_no = trx_sys->max_trx_id;
              • 350  view->low_limit_id = view->low_limit_no;
              • /* The last active transaction has the smallest id: */
              • view->up_limit_id = view->trx_ids[view->n_trx_ids - 1];
          • 这样理解Read View :保存了不应该让这个事务看到的其他的事务 ID 列表
        • 再引入关于可见性的规则
          • 读某一行数据的时候,如果发现他的事务id < up_limit_id (活跃id列表最小值),可见。
          • 如果发现数据的事务id>low_limit_id(ReadView时系统中最大的事务id) ,不可见。
          • 如果发现数据的事务id在列表范围内
            • 如果是id集合中的,不可见
            • 如果不在id集合中,可见
        • 根据上面的规则,以RepeatableRead举个例子吧,要求读一个值,一直读都是同一个值。
          • 这种隔离级别下,开启事务的时候开启一个ReadView,在整个事务过程中都用这个ReadView。
          • 我开启是事务是10,ReadView是 (4,8, 10),【我自己也活跃】,up_limit_id=11,low_limit_id=4
          • 如果我读到一个数据的事务id是1,小于活跃列表的最小值,可见。
            • 为什么?事务开启的时候生成的ReadView,除了4,8,10,其他都已经提交了,所以其实版本<4,以及5、6、7、9,都是肯定在我开启的时候已经提交了。这些版本的的数据,再怎么读都不会变。放心读吧。
          • 如果我读到一个数据的事务id是12,说明他在我创建ReadView之后提交的,我不应该看见这个值,应该去undolog里找这个数据的前面的版本,如果找到<4,或者5、6、7、9都是安全的,可以读。
          • 如果我读到一个数据事务id在活跃列表的范围内
            • 如果就是活跃的事务之一,比如说是8,说明这个数据在我开启事务之后提交了,这个我不能看见,应该去undo log中找上一个版本来读,假设说是7。
            • 7也是在这个活跃范围里,但是并不是活跃事务之一,这个版本是在开启事务之前提交的,这个我可见。
        • 再举个读已提交的例子。
          • 这个隔离级别是每次读都采用新的ReadView。
          • 开启的事务是10。
          • 读一个数据,事务id是9,ReadView活跃id是(4,8,10),按照规则,可见。
          • 过一会再读这个数据,发现事务id变成了11,活跃的id还是(4,8,10),但是因为开启了新的ReadView,当前系统最大事务id>11(因为我们已经读到11了嘛),判断规则是:不在活跃id列表,所以可见。这回就读到了这个数据的新版本了
### 解决SQL中`MVCC_CIRCLE_INFO`标识符的语法错误 遇到 `MVCC_CIRCLE_INFO` 这样的标识符报错情况,通常意味着数据库无法识别该标识符。这可能是由于拼写错误、未创建的对象或者是权限不足等原因造成的。 #### 1. 验证对象存在性 确认 `MVCC_CIRCLE_INFO` 是否确实存在于当前数据库模式下。可以通过查询数据字典视图来验证这一点: ```sql SELECT * FROM information_schema.tables WHERE table_name = 'MVCC_CIRCLE_INFO'; ``` 如果上述命令返回空,则说明此表不存在于任何方案中,需要检查实际存在的名称或路径[^1]。 #### 2. 检查大小写敏感性和限定词 对于某些数据库管理系统(DBMS),如 PostgreSQL,默认情况下是区分大小写的;而对于 MySQL 和 Oracle,在默认配置下不区分大小写但允许使用双引号强制区分。因此,应该确保使用的标识符与定义时保持一致,并考虑加上适当的限定词(schema 名称)。例如: ```sql -- 对于PostgreSQL或其他严格区分大小写的DBMS SELECT * FROM "MySchema"."MVCC_CIRCLE_INFO"; -- 对于MySQL/Oracle等非严格区分大小写的DBMS select * from mydatabase.MVCC_CIRCLE_INFO; ``` #### 3. 权限审查 即使对象存在并正确引用了它,仍然可能因缺乏适当的操作权限而导致访问失败。此时应向管理员请求必要的授权或许可。 #### 4. 使用正确的上下文环境 有时会因为在不同的连接会话之间切换而导致看似合理的语句突然失效。务必保证每次执行 SQL 命令前都处于预期的工作环境中。 #### 5. 替代方法探索 假设以上措施均未能解决问题,那么可以思考是否有其他方式达到相同目的而不必依赖这个特定的名字。比如利用同义词(SYNONYM)或者视图(VIEW)间接操作底层的数据结构。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值