首页 > 编程知识 正文

plsql重新编译存储过程,jdbc数据库连接池

时间:2023-05-06 02:45:22 阅读:166617 作者:2780

文章目录1、MVCC概要2、MVCC实现原理1.2或3个隐藏字段。 2.undo log3.一个序列4.ReadView三.举例说明验证MVCC原理的参考文献

一. MVCC概述

什么是MVCC? MVCC是一种多版本控制协议,InnoDB将MVCC实现为版本控制,以防止出现在当前事务中的数据。

举个例子,在T4,事务a和事务c看到的数据不一致,也就是说有多个版本。

事务时间事务a事务b事务CT1begin; 瓶子; 瓶子; T2select * from transation_test; 结果: id salary

1 1 | | |

| T3 | |插入行数据(2,2 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )。

commit; | |

| T4 | select * from transation_test;

结果: id salary

1 * * * *|| select * from transation _ test;

结果: id salary

1 1

2|

引入MVCC的理由是为了在读写事务时在阅读的情况下不加锁,提高同时性。

二. MVCC的实现原理

理解本质

InnoDB主要使用readview技术来确定当前事务是否可以读取数据。 如果可能的话输出,否则利用undolog构筑历史版本,判断记录是否构筑为最早的版本,或者直到满足可见性条件为止。

上面的工作需要两或三个隐藏字段、undo log、一个数组、ReadView完成。

1 .两个或三个隐藏字段。 InnoDB表的数据组织方法是集群索引。 聚簇索引包含以下附加信息:两个或三个隐藏字段。

DB_TRX_ID :事务处理ID。 指示上次插入或更新记录的事务ID。

DB_ROLL_PTR :指向该记录之前的还原日志记录的回滚指针

DB_ROW_ID :如果表中没有用户主键,则会自动创建InnoDB。 因此,有两个或三个隐藏字段

假设表包含两个字段“ID,Name”,并且插入了事务ID为1的记录“1,事务1”。 此记录还不是以前的版本,回滚指针为空。 现在,该表如下所示。

2 .还原日志之前也介绍过,还原日志在innodb中有两个作用。 MVCC,事务回滚。 还原日志主要包含执行sql语句之前的记录,以及与sql语句相反的操作。

现在,如果出现了修改ID为1的记录的事务,则该过程如下:

首先向InnoDB申请交易ID。 请注意,事务ID会严格增加。 如果申请的ID是3,则简称事务3。

事务3对ID为1的记录执行update更改操作,然后数据库将行锁定该记录。

将此行中的数据复制到还原日志

复制完成后,事务3将ID为1的记录更改为“1,事务3”,事务ID也变为3,回滚指针指向还原日志中记录的事务1版本

事务3提交,解锁。

这里还有一个事务。 修改ID为1的记录

事务再次重复事务3的过程。 如果事务ID为5,则当前图应如下所示

此时,如果事务修改同一记录,则可以看到此记录的还原日志将成为链表的形式。 链条的开头是最新的旧记录,链条的结尾是最古老的记录。

注意事项

还原日志分为插入还原和更新还原。 insert undo是执行insert操作时保留的历史记录。 insert undo将在提交/回滚事务后直接删除,但update undo仍作为历史版本的链表保留。 正如您所看到的,上面没有删除事务1的insert undo

3 .数组在InnoDB内部保持了数组。该数组(trx_sys-descriptors数组)会记录当前还未提交的事务id,id按从小到大的顺序排序。 这意味着当事务执行时,InnoDB将请求事务id,数组将记录此id,并在事务提交时将其从数组中删除。

这个数组有什么用? 以下面的ReadView为基础,创建ReadView时会将数组复制到ReadView中,ReadView根据数组中未提交的id值确定事务是否显示记录。

4.ReadView 什么是ReadView?

阅读视图,阅读视图。 在代码级别,ReadView实际上是一个名为read_view_t的结构(c语言名词)。 事务也是一个结构,即trx_t。 对于每个数据库连接,均具有一个trx_t (事务),对于每个trx_t (事务,均为一个read_view_t )读取视图); 由事务的快照读取操作生成的读视图。

ReadView有什么用?

上述ReadView主要用于确定事务的可见性。 这意味着某个事务执行快照读取时

该记录创建一个ReadView读视图,根据ReadView去判断当前事务能够看到哪个版本数据,有可能是最新的数据,也有可能是该行记录undo log里面某个版本的数据。

ReadView如何做可见性判断?
回答这个问题要从ReadView结构体中的属性入手了。
read_view_t

descriptors数组(readview数组):拷贝记录当前活跃事务id的trx_sys->descriptors到该数组中up_limit_id:记录该数组中的最小值(min_trx_id有点反人类,up对应min)low_limit_id:记录系统还未分配给事务的id,该值大于descriptors数组中的最大值(因为还没分配给事务的id是创建readview时刻当前系统中最大的,InnoDB从小到大给事务分配)。

这几个属性有什么用呢?利用上述属性做事务可见性判断

判断的核心思想是事务启动以前及以后所有还没提交的事务,它都不可见。源码如下

//id:一条记录的事务idbool changes_visible(trx_id_t id, const table_name_t &name) const MY_ATTRIBUTE((warn_unused_result)) { ut_ad(id > 0); //如果这条记录的事务id<数组中最小值 或者 等于当前事务id,返回true那么当前事务可见这条记录 if (id < m_up_limit_id || id == m_creator_trx_id) { return (true); } check_trx_id_sanity(id, name); //如果这条记录的事务id大于等于最大事务id,返回false那么当前事务不可见这条记录 if (id >= m_low_limit_id) { return (false); } else if (m_ids.empty()) { return (true); } const ids_t::value_type *p = m_ids.data(); return (!std::binary_search(p, p + m_ids.size(), id));}

为了方便理解,下面对上面的代码做进一步的说明,一共分四种情况

如果最新记录上事务id<up_limit_id(min_trx_id),证明当前事务构建readview时这个事务已经提交了,所以可以看见这条记录

如果最新记录上事务id>=low_limit_id(max_trx_id),证明当前事务构建readview时这个事务还没有对记录进行修改操作,所以看不见这条记录

如果最新记录上事务id在up_limit_id和low_limit_id之间,且在readview数组中,证明当前事务构建readview时这个事务正在修改该条记录,所以看不见这条记录

如果最新记录上事务id在up_limit_id和low_limit_id之间,且不在readview数组中,证明当前事务构建readview时这个事务已经提交,所以可以看见这条记录

是不是字太多,记这么多东西简直是难为人。

总结下最核心的,InnoDB的事务快照读的情况下只能看见已经提交事务的数据,已经提交分为两种情况

一条记录事务id<up_limit_id,证明当前事务构建readview时这个事务已经提交了,所以可以看见这条记录一条记录事务id在readview数组范围中,但不在readview数组中,也可以证明事务已经提交了

如果满足其中一种情况,事务则可以看见该记录

三、举例验证MVCC原理

事务隔离级别为可重复读。当前系统中有5个事务,5个事务都对id为1这行记录进行操作。
其中事务1和事务5已经提交,事务8进行快照读。

时刻事务1事务3事务5事务7事务8T1begin;begin;begin;begin;begin;T2插入(1,事务1)记录commit;T3修改id为1的名字为事务3修改id为1的名字为事务5commit;修改id为1的名字为事务7;​查询id为1的记录(快照读)

事务8在T4时刻快照读创建ReadView,在T4时刻可以读取到事务几的数据呢?

首先看T4时刻ReadView中各个属性的值为多少

ReadView数组:拷贝全局未提交事务id,即[3,7,8]up_limit_id:记录readview数组中最小值为3low_limit_id:记录系统尚未分配的事务id为9

根据前面所说隐藏字段及undo log版本链,可以做成如下图

最后得出结论,事务8可以读取到事务5版本的数据

需要注意的是:
MVCC可以通过ReadView的方式实现读已提交和可重复读的隔离级别,但是两种隔离级别创建的ReadView的时间点不同。

读已提交会在每次Select创建一个ReadView可重复读是第一次select之后创建ReadView,之后再select都会复用。

因此可重复读的隔离级别解决了不可重复读的问题,并一定程度上避免了幻读问题,但是没有真正结解决,请看下一篇

参考文献

事务实现源码级:http://mysql.taobao.org/monthly/2018/11/04/
事务概括:http://mysql.taobao.org/monthly/2017/12/01/
通俗易懂级MySQL MVCC
深入理解MVCC:https://www.cnblogs.com/kismetv/p/10331633.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。