当前位置: 首页 > 知识库问答 >
问题:

事务隔离级别与表上的锁的关系

岑叶秋
2023-03-14

我已经阅读了大约4个级别的隔离:

Isolation Level       Dirty Read    Nonrepeatable Read  Phantom Read  
READ UNCOMMITTED      Permitted       Permitted           Permitted
READ COMMITTED              --        Permitted           Permitted
REPEATABLE READ             --             --             Permitted
SERIALIZABLE                --             --              --

我想了解每个事务隔离在表上使用的锁

READ UNCOMMITTED - no lock on table
READ COMMITTED - lock on committed data
REPEATABLE READ - lock on block of sql(which is selected by using select query)
SERIALIZABLE - lock on full table(on which Select query is fired)

以下是事务隔离中可能出现的三种现象
脏读取-无锁定
不可重复读取-无脏读取作为对提交数据的锁定
幻影读取-锁定sql块(使用select query选择)

我想了解我们在哪里定义这些隔离级别:仅在jdbc/hibernate级别或在DB中定义

PS:我已经浏览了oracle中隔离级别的链接,但是它们看起来很笨拙,而且只针对数据库

共有3个答案

西门智
2023-03-14

锁总是在数据库级别获取。

来自甲骨文官方文件:

为了避免事务期间发生冲突,DBMS 使用锁,即阻止其他人访问事务正在访问的数据的机制。(请注意,在自动提交模式下,每个语句都是一个事务,只保留一个语句的锁。设置锁后,它将保持有效,直到提交或回滚事务。例如,DBMS 可以锁定表的一行,直到提交对表的更新。此锁的作用是防止用户进行脏读取,即在永久读取值之前读取值。(访问尚未提交的更新值被视为脏读,因为该值可能会回滚到其以前的值。如果读取稍后回滚的值,则将读取无效值。

如何设置锁取决于所谓的事务隔离级别,从完全不支持事务到支持强制执行非常严格的访问规则的事务。

事务隔离级别的一个示例是TRANSACTION_READ_COMMITTED,它将不允许访问一个值,直到它被提交之后。换句话说,如果事务隔离级别设置为TRANSACTION_READ_COMMITTED,则DBMS不允许发生脏读。接口连接包括五个值,它们代表您可以在JDBC中使用的事务隔离级别

慕鹏
2023-03-14

正如brb tea所说,取决于数据库实现和他们使用的算法:MVCC或两相锁定。

CUBRID(开源RDBMS)解释了这两种算法的思想:

  • 两相锁定(2PL)

第一个是当T2事务试图更改A记录时,它知道T1事务已经更改了A记录,并等待直到T1事务完成,因为T2事务无法知道T1交易将被提交还是回滚。这种方法称为两相锁定(2PL)。

    < li >多版本并发控制(MVCC)

另一个是允许它们中的每一个(T1 和 T2 事务)都有自己的更改版本。即使 T1 事务已将 A 记录从 1 更改为 2,T1 事务也会保留原始值 1,并写入 A 记录的 T1 事务版本为 2。然后,以下 T2 事务将 A 记录从 1 更改为 3,而不是从 2 更改为 4,并写入 A 记录的 T2 事务版本为 3。

当回滚T1事务时,2,即T1事务版本,不应用于A记录并不重要。之后,如果提交T2事务,则3,即T2事务版本,将应用于A记录。如果在T2事务之前提交T1事务,则A记录更改为2,然后在提交T2事务时更改为3。最终的数据库状态与独立执行每个事务的状态相同,对其他事务没有任何影响。因此,它满足ACID属性。这种方法称为多版本并发控制(MVCC)。

MVCC允许并发修改,但代价是增加了内存开销(因为它必须维护同一数据的不同版本)和计算(在REPETEABLE_READ级别,您不能丢失更新,因此它必须检查数据的版本,就像Hiberate对Optimistick锁定所做的那样)。

在2PL中,事务隔离级别控制以下内容:

>

  • 读取数据时是否获取锁,以及请求哪种类型的锁。

    读锁持有多长时间。

    读取操作是否引用由另一个事务修改的行:

    >

  • 块,直到释放行上的排他锁。

    检索语句或事务启动时存在的行的已提交版本。

    读取未提交的数据修改。

    选择事务隔离级别不会影响为保护数据修改而获取的锁。无论为事务设置的隔离级别是什么,事务总是获得它所修改的任何数据的独占锁,并一直持有该锁,直到事务完成。对于读操作,事务隔离级别主要定义防止其他事务修改的影响的保护级别。

    较低的隔离级别提高了许多用户同时访问数据的能力,但增加了用户可能遇到的并发影响的数量,如脏读或丢失更新。

    SQL服务器中锁和隔离级别之间关系的具体示例(使用2PL,READ_COMMITTED_SNAPSHOT=ON的READ_COMMITED除外)

    >

  • READ_UNCOMMITED:不要发布共享锁以防止其他事务修改当前事务读取的数据。READ UNCOMMITTED事务也不会被独占锁阻止,这将阻止当前事务读取已被其他事务修改但未提交的行。[...]

    读取提交:

    • 如果READ_COMMITTED_SNAPSHOT设置为OFF(默认值):当当前事务正在运行读取操作时,使用共享锁防止其他事务修改行。共享锁还阻止语句读取其他事务修改的行,直到其他事务完成。[…]在处理下一行之前释放行锁。[…]
    • 如果READ_COMMITTED_SNAPSHOT设置为ON,数据库引擎将使用行版本控制为每条语句提供一个事务一致的数据快照,就像它在语句开始时一样。锁不用于保护数据免受其他事务的更新

    REPETEABLE_READ:共享锁放置在事务中每个语句读取的所有数据上,并一直保持到事务完成。

    SERIALIZABLE:范围锁放在与事务中执行的每个语句的搜索条件相匹配的键值范围内。[...]范围锁一直保持到事务完成。

  • 羿季
    2023-03-14

    我想了解每个事务隔离对表的锁定

    例如,您有3个并发进程A、B和c。A启动事务、写入数据和提交/回滚(取决于结果)。b只是执行一个< code>SELECT语句来读取数据。读取和更新数据。所有这些过程都在同一个表t上工作。

    • 读取未提交 - 表上没有锁。您可以在写入表时读取表中的数据。这意味着 A 写入数据(未提交),B 可以读取这些未提交的数据并将其用于任何目的。如果 A 执行回滚,B 仍已读取数据并使用它。这是处理数据的最快但最不安全的方式,因为可能会导致物理上不相关的表中出现数据漏洞(是的,两个表在实际应用程序中可以在逻辑上但不具有物理相关性=\)。
    • 已提交读取 - 锁定已提交的数据。您可以读取仅提交的数据。这意味着 A 写入数据,B 无法读取 A 保存的数据,直到 A 执行提交。这里的问题是 C 可以更新在 B 客户端上读取和使用的数据,而 B 客户端不会有更新的数据。
    • 可重复读取 - 锁定 SQL 块(通过使用选择查询选择)。这意味着 B 在某种条件下读取数据,即 WHERE aField

    我想了解我们在哪里定义这些隔离级别:仅在 JDBC/hibernate 级别或在数据库中也

    使用JDBC,您可以使用连接#setTransactionIsolation来定义它。

    使用Hibernate:

    <property name="hibernate.connection.isolation">2</property>
    

    在哪里

      < li>1:读取未提交的数据 < li>2:已提交读取 < li>4:可重复读取 < li>8:可序列化

    Hibernate配置取自这里(对不起,这是西班牙语)。

    顺便说一下,您也可以在RDBMS上设置隔离级别:

      < li>MySQL隔离级别, < li>SQL Server隔离级别 < li>Informix隔离级别(个人注意:我永远不会忘记< code > SET ISOLATION TO DIRTY READ 这句话。)

    等等...

     类似资料:
    • 研究隔离级别和阻塞,更具体的读提交与读提交快照。 在SQL Server 2014中,默认隔离级别是提交读取,如果我运行 然后在新的连接中 第二个查询将阻塞并挂起。 然而,在Azure SQL中,隔离级别是READ COMMITTED SNAPSHOT,它似乎允许从Person读取。持TABLOCKX的人在等待。 问:如何重现阻塞场景,可能有提示,强制第一个SELECT完全阻塞表,同时打开READ

    • 我试图理解锁定如何与隔离级别一起工作。我已经回答了这个问题,但无法理解给定打击的流 在这里,我在不同的终端中启动两个事务,并在其中读取同一行。当我尝试更新它们时,两个终端都在等待更新。除此之外,没有其他查询正在运行 这是我做的一系列步骤 这是我的第一个问题 这里我想了解为什么两个连接都在等待,以及它们是否是谁拥有更新行的锁? 如果我将上述步骤更改为 在这种情况下,不同的是我可以看到conn1有锁,

    • 本文向大家介绍事务的隔离级别有哪些?相关面试题,主要包含被问及事务的隔离级别有哪些?时的应答技巧和注意事项,需要的朋友参考一下 SQL 标准定义了四个隔离级别: READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。 READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重

    • 本文向大家介绍MySQL的默认事务隔离级别是?相关面试题,主要包含被问及MySQL的默认事务隔离级别是?时的应答技巧和注意事项,需要的朋友参考一下 读未提交(RU): 一个事务还没提交时, 它做的变更就能被别的事务看到. 读提交(RC): 一个事务提交之后, 它做的变更才会被其他事务看到. 可重复读(RR): 一个事务执行过程中看到的数据, 总是跟这个事务在启动时看到的数据是一致的. 当然在可重复

    • 本文向大家介绍mysql的事务,隔离级别和锁用法实例分析,包括了mysql的事务,隔离级别和锁用法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了mysql的事务,隔离级别和锁用法。分享给大家供大家参考,具体如下: 事务就是一组一起成功或一起失败的sql语句。事务还应该具备,原子性,一致性,隔离性和持久性。 一、事务的基本要素 (ACID) 1、原子性:事务开始后,所有的操作,要么

    • 我有一个对具有 SQL API 的 Cosmos 容器的长期运行查询,该查询需要 10 分钟以上才能完成。有没有办法将数据库的隔离级别设置为“可重复读取”或“可序列化”,以避免幻像读取,如这里所定义的那样? 我知道我们可以为 Cosmos DB 设置一致性级别,但它仅适用于地质副本之间的读/写一致性,而不适用于事务隔离。