当前位置:首页 > Web开发 > 正文

key in query results = [%s]

2024-03-31 Web开发

标签:

Fabric 1.4 源码分析 MVCC验证

读本节文档之前建议先检察[Fabric 1.4 源码分析 committer记账节点]章节。

1. MVCC简介

Multi-Version Concurrency Control 多版本并发控制,MVCC 是一种并发控制的要领,一般在数据库打点系统中,实现对数据库的并发访谒。在数据库系统中,锁机制可以控制并发操纵,但是其系统开销较大,而MVCC可以在大大都情况下取代行级锁,使用MVCC,能降低其系统开销。MVCC是通过生存数据在某个时间点的快照来实现的. 差别存储引擎的MVCC. 差别存储引擎的MVCC实现是差此外,范例的有乐不雅观并发控制和灰心并发控制.

2. MVCC样例介绍

InnoDB的MVCC,是通过在每行记录后面生存两个隐藏的列来实现的,这两个列,分袂生存了这个行的创建时间,一个生存的是行的删除时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID。此中MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个断绝级别下事情。

SELECT
InnoDB会按照以下两个条件查抄每行纪录:
InnoDB只查找版本早于当前事务版本的数据行,即,==行的系统版本号小于或即是事务的系统版本号==,这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者改削过的。
==行的删除版本,要么不决义,要么大于当前事务版本号==。这样可以确保事务读取到的行,在事务开始之前未被删除。
只有切合上述两个条件的纪录,才华作为盘问功效返回。

INSERT
InnoDB为插入的每一行生存当前系统版本号作为行版本号。

DELETE
InnoDB为删除的每一行生存当前系统版本号作为行删除标识。

UPDATE
InnoDB为插入一行新纪录,生存当前系统版本号作为行版本号,同时,生存当前系统版本号到本来的行作为行删除标识。

长处
生存这两个特别系统版本号,使大大都读操纵都可以不用加锁。这样设计使得读数据操纵很简单,性能很好。
错误谬误
每行纪录都需要特别的存储空间,需要做更多的行查抄事情,以及一些特别的维护事情

3. Fabric里面MVCC的实现

这里回顾几个常识点:

状态由键值对构成。所有键值条目都是带有版本的

键的版本只记录在读集中;写集只包罗键和交易设置的键的最新值

使用读写集中的读集来验证交易,使用写集来更新受影响的键的版本和值

使用交易的高度来作为版本号

3.1 验证大众数据读集key

读集中键的版本和世界状态中键的版本一致就认为该交易是 合法的。

if !version.AreSame(committedVersion, rwsetutil.NewVersion(kvRead.Version)) { return false, nil } 版本数据布局 type Version struct { BlockNum uint64 TxNum uint64 }

当验证完一笔交易后,如果交易有效,,会更新key版本,接着再验证下一笔交易。

committingTxHeight := version.NewHeight(block.Num, uint64(tx.IndexInBlock)) updates.ApplyWriteSet(tx.RWSet, committingTxHeight, v.db)

在此举例介绍,mycc链码a转账给b。
实例化链码交易在区块3中,则a、b版本为

{ "key": "a", "version": { "block_num": "3", "tx_num": "0" } }

倡议一笔有效交易后,版本更新为

{ "key": "a", "version": { "block_num": "4", "tx_num": "0" } } 3.2 验证range-query

当读写集中包罗一个或多个盘问信息(query-info)时,需要执行特别的验证。这种特别的验证需要确保在按照盘问信息获得的功效的超集(多个范畴的合并)中没有插入、删除或者更新键。

"range_queries_info": [ { "end_key":"marble3", "itr_exhausted":true, "raw_reads":{ "kv_reads":[ { "key":"marble1", "version":{ "block_num":"8", "tx_num":"0" } }, { "key":"marble2", "version":{ "block_num":"9", "tx_num":"0" } } ] }, "start_key":"marble1" } ]

validate()要领会按照rangeQueryInfo是否包罗了合法当梅克尔树摘要东西返回差别当验证要领。

if rangeQueryInfo.GetReadsMerkleHashes() != nil { logger.Debug(`Hashing results are present in the range query info hence, initiating hashing based validation`) // 暂时全局搜索只发明ReadsMerkleHashes读,没发明写 validator = &rangeQueryHashValidator{} } else { logger.Debug(`Hashing results are not present in the range query info hence, initiating raw KVReads based validation`) validator = &rangeQueryResultsValidator{} }

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/32299.html