InnoDB---读未提交隔离级别的实现

读未提交的实现

对于读未提交隔离级别,此级别不会对记录加锁,有如下几种情况:


对系统表的数据操作,是数据引擎自己发出的数据查询操作,使用读未提交隔离级别,目的是不与其它事务因锁的存在而冲突。


在row_search_mvcc()、row_sel_get_clust_rec_for_mysql()等获取记录的函数中确保读未提交隔离级别下允许读到最新的记录

那么,怎么才能读到最新的记录呢?以row_search_mvcc()为例, 我们来看代码实现方式:对于读未提交的隔离级别,代码什么也没有做,默认本函数的“PHASE 4”调用“rec = btr_pcur_get_rec(pcur);”获得的rec就是可用的。如果不是读未提交的隔离级别,才判断rec的可见性,rec不可见时才去找旧版本。所以,InnoDB以此方式,实现了读未提交隔离级别。与此方式类似的处理,还有row_sel_get_clust_rec_for_mysql()函数,读者可以参考阅读。

row_search_mvcc(...)  //获取记录

{...

/* We are
ready to look at a possible new index entry in the result

set: the cursor is now placed on a user
record */

if (prebuilt->select_lock_type
!= LOCK_NONE) {  //如果需要加锁,则加锁的语义来自上层

...

} else {  //不需要加锁

/*
This is a non-locking consistent read: if necessary, fetch a previous version
of the record */

if
(trx->isolation_level == TRX_ISO_READ_UNCOMMITTED)
{ //如果是读未提交,则什么也不做

/* Do nothing: we let a non-locking SELECT read the latest version of
the record */

}
else if (index == clust_index) { //否则,才需要检查“rec”是否满足可见性,不满足则找出满足可见性要求的旧版本

//所以,读未提交什么也不做,就是在说当前的rec是符合的,能被读到的,根本不用到回滚段找出旧版本(所得即所“可见”)

/*  Fetch a previous version of
the row if the current one is not visible in the snapshot;

if we have a very high force recovery level
set, we try to avoid crashes by skipping this lookup */

if (srv_force_recovery < 5

&& !lock_clust_rec_cons_read_sees(rec,
index, offsets, trx_get_read_view(trx))) {

rec_t*    old_vers;

/* The following call returns ‘offsets‘ associated with ‘old_vers‘ */

err = row_sel_build_prev_vers_for_mysql(trx->read_view,
clust_index, prebuilt, rec, &offsets, &heap,

&old_vers,
need_vrow ? &vrow : NULL, &mtr);

if (err != DB_SUCCESS) {

goto lock_wait_or_error;

}

if (old_vers == NULL) {

/* The row did not exist yet in the read view */

goto next_rec;

}

rec = old_vers;

}

}
else {

/* We are looking into a non-clustered
index, and to get the right version of the record we

have to look also into the clustered index:
this is necessary, because we can only get the undo

information via the clustered index record.
*/

...

}

}

}

...}

时间: 2025-01-31 14:46:39

InnoDB---读未提交隔离级别的实现的相关文章

数据库隔离级别,读已提交,读未提交

同样是后端开发,年薪50万和年薪20万的差距在哪里>>> 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复读.幻读这几类问题. √: 可能出现    ×: 不会出现 事务的隔离级别 脏读 不可重复读 幻读 Read uncommitted √ √ √ Read committed--Sql Server , Oracle × √ √ Re

数据库事务隔离级别--读未提交,读已提交,重复读,序列化

参考原文:https://my.oschina.net/bigdataer/blog/1976010 上一篇文章讲述了:数据库主从复制,那么新的问题数据库读写分离对事物是否有影响? 1. 名词 读未提交read-uncommited 读已提交read-commited 重复读repeatable-->可能产生主从数据不一致问题 串行化serializable-->特殊场景-秒杀使用,一般不用 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committe

SQL Server 中的事务与事务隔离级别以及如何理解脏读, 未提交读,不可重复读和幻读产生的过程和原因

原本打算写有关 SSIS Package 中的事务控制过程的,但是发现很多基本的概念还是需要有 SQL Server 事务和事务的隔离级别做基础铺垫.所以花了点时间,把 SQL Server 数据库中的事务概念,ACID 原则,事务中常见的问题,问题造成的原因和事务隔离级别等这些方面的知识好好的整理了一下. 其实有关 SQL Server 中的事务,说实话因为内容太多, 话题太广,稍微力度控制不好就超过了我目前知识能力范围,就不是三言两语能够讲清楚的.所以希望大家能够指出其中总结的不足之处,对我

SQLServer之创建事务未提交读

未提交读注意事项 使用 SET TRANSACTION ISOLATION LEVEL 指定会话的锁定级别. 一次只能设置一个隔离级别选项,而且设置的选项将一直对那个连接始终有效,直到显式更改该选项为止. 事务中执行的所有读取操作都会在指定的隔离级别的规则下运行,除非语句的 FROM 子句中的表提示为表指定了其他锁定行为或版本控制行为. 事务隔离级别定义了可为读取操作获取的锁类型. 在事务进行期间,可以随时将事务从一个隔离级别切换到另一个隔离级别,但有一种情况例外. 即在从任一隔离级别更改到 S

事务隔离级别区分,未提交读,提交读,可重复读

事务隔离超通俗好懂的的讲解 按照隔离的级别由低到高,越高的隔离,效率越差 0).DEFAULT 默认隔离级别,由数据库的数据隔离级别确定隔离级别       1).READ_UNCOMMIYTTED 都未提交的 级别最低             允许别的事务,去读取这个事务为提交之前的数据             缺点:可能会造成脏读.幻读.不可重复读.             例子讲解:店家对1000元商品进行降价500处理,数据更改,但未提交事务:             然后你查到降价将货

mysql事务未提交导致锁等待如何解决

1.实验环境 Myql版本5.7.17-log 实验表结构 ([email protected])[apex]> show create table test; +-------+-----------------------------------------------------------------------------------------------------------------------------------+ | Table| Create Table      

曲苑杂坛--DML操作中如何处理那些未提交的数据

对数据库稍有了解的人,数据库使用排他锁X锁来避免两个事务同时修改同一条数据,同时使用较低级别如行上加锁来提高并发度. 以下了两种场景很容易理解: 1>事务1执行 UPDATE TB1 SET C2=1 WHERE C1=1(此处假设C1为主键,使用行锁),事务1未提交,而后事务2执行UPDATE TB1 SET C2=2 WHERE C1=1,事务2必须等到事务1提交或回滚后,才能获得对该行数据的X锁: 2>事务1执行 UPDATE TB1 SET C2=1 WHERE C1=1(此处假设C1

找出未提交的MySQL线程/事务

找出未提交的MySQL线程/事务: SELECT trx_id,trx_state,trx_started,trx_mysql_thread_id,CURRENT_TIMESTAMP - trx_started AS RUN_TIME from information_schema.innodb_trx; SELECT * from information_schema.processlist;   这个能看到上面哪个SQL线程ID(下图的378号线程就是造成MDL锁的罪魁祸首) SELECT

SQL Server查詢未提交事務,終止進程,解除表鎖

如果數據庫中有未提交的事務,相關表將一直處於死鎖狀態,從而影響其他進程的查詢(除非在查詢中用with (nolock)). 由於事務的隔離性,其他Session無法簡單通過RollBack Transaction來回滾事務,只能終止未提交事務所在會話的進程,然後由於事務的原子性,終止其進程,事務也就回滾了. 如何找出未提交的事務呢 運行如下命令: DBCC OpenTran 結果如下: SPID即進程ID,再運行如下命令,終止進程即可: kill 52 -- 52就是未提交事務會話所在SPID