我读过关于隔离的四个层次:
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)
以下是在事务隔离中可能发生的三种现象Dirty Read
-无锁定Nonrepeatable Read
-没有脏读作为提交数据的锁Phantom Read
-锁在sql的块上(使用select query选择)
我想了解我们在哪里定义这些隔离级别:仅在jdbc/hibernate级别或在数据库中
PS:我已经通过在Isolation levels in oracle的链接,但他们看起来笨拙和谈论数据库的具体
4条答案
按热度按时间mqkwyuun1#
我想了解每个事务隔离对表的锁
例如,您有3个并发进程A、B和C。A启动一个事务,写数据和提交/回滚(取决于结果)。B只执行
SELECT
语句来读取数据。C读取和更新数据。所有这些过程都在同一台T上工作。*READ UNCOMMITTED-表上没有锁。您可以在写入表的同时读取表中的数据。这意味着A写入数据(未提交),B可以读取此未提交的数据并使用它(用于任何目的)。如果A执行回滚,B仍然读取并使用了数据。这是处理数据最快但最不安全的方法,因为可能会导致物理上不相关的表中出现数据漏洞(是的,在现实世界的应用程序中,两个表可以在逻辑上但在物理上不相关=\)。
*READ COMMITTED-锁定已提交的数据。您可以读取仅提交的数据。这意味着A写入数据,B不能读取A保存的数据,直到A执行提交。这里的问题是C可以更新在B上读取和使用的数据,而B客户端将没有更新的数据。
*REPEATABLE READ-锁定SQL块(使用select query选择)。这意味着B在某种条件下读取数据,即
WHERE aField > 10 AND aField < 20
,A插入aField
值在10和20之间的数据,然后B再次读取数据并获得不同的结果。*SERIALIZABLE-对全表(触发Select查询的表)锁定。这意味着,B读取数据并且没有其他事务可以修改表上的数据。这是最安全但最慢的数据处理方式。此外,由于一个简单的读操作会锁定表,这可能会导致生产上的严重问题:假设T表是一个Invoice表,用户X想要知道当天发票,而用户Y想要创建一个新的发票,因此当X执行发票的读取时,Y不能添加新的发票(当涉及到钱的时候,人们会非常生气,尤其是老板)。
我想了解我们在哪里定义这些隔离级别:仅在JDBC/hibernate级别或也在DB中
使用JDBC时,您可以使用
Connection#setTransactionIsolation
来定义它。使用Hibernate:
在哪里
Hibernate配置取自here(对不起,是西班牙语)。
顺便说一下,你也可以在RDBMS上设置隔离级别:
SET ISOLATION TO DIRTY READ
句子。一遍又一遍
cidc1ykv2#
正如brb tea所说,这取决于数据库实现和他们使用的算法:MVCC或两相锁定。
CUBRID(开源RDBMS)explains这两个算法的思想:
第一种是当T2事务试图改变A记录时,它知道T1事务已经改变了A记录,并且等待直到T1事务完成,因为T2事务不知道T1事务将被提交还是回滚。这种方法被称为两相锁定(2PL)。
另一个是允许T1和T2事务中的每一个都有自己的更改版本。即使当T1事务已经将A记录从1改变为2时,T1事务也保持原始值1不变,并且写入A记录的T1事务版本为2。然后,随后的T2事务将A记录从1变为3,而不是从2变为4,并且写入A记录的T2事务版本是3。
回滚T1事务时,T1事务版本2是否未应用于A记录并不重要。之后,如果T2事务被提交,则3(T2事务版本)将被应用于A记录。如果T1事务在T2事务之前提交,则A记录被改变为2,然后在提交T2事务时改变为3。最终的数据库状态与独立执行每个事务的状态相同,对其他事务没有任何影响。因此,它满足ACID属性。这种方法称为多版本并发控制(MVCC)。
MVCC允许并发修改,但代价是增加了内存开销(因为它必须维护相同数据的不同版本)和计算(在REPETEABLE_READ级别中,您不能放松更新,因此它必须检查数据的版本,就像Hiberate使用Optimistick Locking一样)。
在2PL Transaction isolation levels control the following中:
选择事务隔离级别不会影响为保护数据修改而获取的锁。事务始终对它修改的任何数据获取排他锁,并在事务完成之前一直持有该锁,而不管为该事务设置的隔离级别。对于读操作,事务隔离级别主要定义了保护级别,以免受其他事务所做修改的影响。
较低的隔离级别可提高多个用户同时访问数据的能力,但也会增加并发效应的数量,例如用户可能遇到的脏读或更新丢失。
SQL Server中锁和隔离级别之间关系的具体示例(除了READ_COMMITTED_SNAPSHOT=ON的READ_COMMITTED上使用2PL)
zsohkypk3#
锁总是在数据库级别获取。
Oracle official document:
为了避免事务期间的冲突,DBMS使用锁,用于阻止其他人访问事务正在访问的数据的机制。(请注意,在自动提交模式下,每个语句都是一个事务,锁只针对一个语句持有。)设置锁后,它将一直有效,直到事务被提交或回滚。例如,DBMS可以锁定表的一行,直到提交了对它的更新。此锁的作用是防止用户进行脏读,即在将值变为永久值之前阅读该值。(访问尚未提交的更新值被认为是“脏读”,因为该值可能会回滚到其先前的值。如果读取的值后来被回滚,则读取的值无效。)
如何设置锁是由所谓的事务隔离级别决定的,该级别的范围可以从根本不支持事务到支持执行非常严格的访问规则的事务。
事务隔离级别的一个示例是
TRANSACTION_READ_COMMITTED
,它不允许在提交值之前访问该值。换句话说,如果事务隔离级别设置为TRANSACTION_READ_COMMITTED
,则DBMS不允许发生脏读。接口Connection
包括五个值,它们表示可以在JDBC中使用的事务隔离级别q9yhzks04#
关于READ COMMITTED -我认为一个更好的例子来证明它如下:
假设:数据a =10;螺纹A、B、C
如果我说错了请纠正我。