如果另一个查询编辑了这些结果,数据库如何保持结果

时间:2014-07-11 03:14:17

标签: mysql database postgresql relational-database mariadb

我只是想知道如果另一个查询编辑了您正在处理的那些行,大多数关系数据库如何处理维护您的结果集。例如,如果我执行了类似100k行的select并且我仍在提取那些另一个查询,则会在尚未读取的其中一行上执行update {{1在获取这些行时不会看到它,我想知道数据库引擎如何处理它。如果您只有一种类型的数据库的详细信息,那么无论如何我都希望听到它。

3 个答案:

答案 0 :(得分:3)

请查找多版本并发控制。不同的数据库有不同的方法来管理它。对于MySQL,InnoDB,您可以尝试http://dev.mysql.com/doc/refman/5.0/en/innodb-multi-versioning.html。 PostgreSQL - https://wiki.postgresql.org/wiki/MVCC。这是一个很棒的演讲 - http://momjian.us/main/writings/pgsql/mvcc.pdf。它在此线程Database: What is Multiversion Concurrency Control (MVCC) and who supports it?

中的stackoverflow中进行了解释

答案 1 :(得分:1)

您在并发编程(Wikipedia concurrency control)中描述的一般目标是序列化(Wikipedia serializability):一个实现管理数据库,就好像事务发生时没有重叠一样。

这一点的重要性在于,只有这样,系统才会按照我们通常解释的方式按照代码描述的方式行事。否则,操作结果是同时执行的所有进程的组合。然而,通过具有有限类别的非正常非隔离所谓的异常行为,可以增加事务吞吐量。所以那些实现技术也是适用的。 (例如MVCC。)但要理解:这种非序列化行为将一个事务与另一个事务隔离开来。 (即所谓的“隔离”级别实际上是非隔离级别。)

通过将事务实现分解为基于读取和写入共享资源的片段来管理隔离,并且执行它们与来自其他事务的片断交织,使得效果与某些非重叠执行序列相同。粗略地说,人们可以“悲观地”“锁定”来自更改资源的其他进程,并让他们等待或“乐观地”“版本化”数据库,并在更改不可调和时(回滚)丢弃(抛弃)某些进程的工作(不可序列化)

基于对主要产品的实施者的可串行化理解的一些技术在this answer中。有关相关概念和技术,请参阅维基百科文章或数据库教科书。例如,Ramez Elmasri和他的数据库系统的基础知识。 Shamkant B. Navathe。 (许多教科书,幻灯片和课程都是免费在线的。)

(两个答案和对你的问题的评论提到MVCC。正如我评论的那样,MVCC不仅仅是一种实现技术,它甚至不支持事务序列化,即实际上隔离事务就像每次都完成所有事务一样。它允许某些类型的错误(也就是异常)。它必须与其他技术混合进行隔离.MVCC的回答,评论和upvoting反映了一种流行的和有价值的技术之间的混淆,用于有用和有限的失败根据你的问题与实际的核心问题和手段进行隔离。)

答案 2 :(得分:0)

正如Jayadevan指出的那样,最广泛使用的数据库使用的一般原则允许您在读取值时进行修改multi-version concurrency control or MVCC。支持读取行更新的所有广泛使用的现代RDBMS 实现依赖于行版本控制的一些概念。

实施细节不同。 (我将在这里解释一下PostgreSQL,但你应该接受Jayadevan的回答而不是我的。)

PostgreSQL uses transaction ID ranges to track row visibility。因此,表格中的元组会有多个副本,但任何给定的交易都只能"参见"其中之一。每个事务都有一个唯一的ID,较新的事务具有较新的ID。每个元组都隐藏了xminxmax字段,用于跟踪哪些交易可以"查看"元组。通过设置元组xmin来实现插入,以便具有较低xid的事务知道在读取表时忽略元组。通过设置元组xmax来实现删除,以便具有更高xid的事务知道在读取表时忽略元组。通过有效删除旧元组(设置xmax)然后插入新元组(设置xmin)来实现更新,以便旧事务仍然可以看到旧元组,但新事务会看到新元组。当没有正在运行的事务仍然可以看到已删除的元组时,vacuum将其标记为可覆盖的可用空间。

Oracle使用撤消和重做日志,因此主表中只有一个元组副本,而想要查找旧版本的事务必须在日志中找到它。与PostgreSQL一样,它使用行版本控制,但我对细节不太确定。

现在几乎所有其他数据库都使用类似的方法。过去依赖锁定的那些,比较旧的MS-SQL版本,已经转移到MVCC。

MySQL使用带有InnoDB表的MVCC,现在是默认值。 MyISAM表仍然依赖于表锁定(但它们也会占用您的数据,所以不要将它们用于您关心的任何事情)。

一些嵌入式数据库(如SQLite)仍然只依赖于表锁定 - 这往往需要较少的浪费磁盘空间和I / O开销,但代价是并发性大大降低。如果对表进行独占锁定,某些数据库允许您绕过MVCC。

(标记为社区wiki,因为我也对这个问题进行了密切投票)。

您还应该阅读transaction isolationlocking上的PostgreSQL文档,以及您使用的其他数据库的类似文档。请参阅isolation上的维基百科文章。