我已经阅读了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)
以下是事务隔离中可能发生的三种现象
脏读 - 没有锁定
不可重复读 - 没有脏读作为已提交数据的锁定
Phantom Read - 锁定sql块(使用select查询选择)
我想了解我们在哪里定义这些隔离级别:仅在jdbc / hibernate级别或在DB中
PS:我已经浏览了Isolation levels in oracle中的链接,但是它们看起来很笨拙并且谈论数据库特定的
答案 0 :(得分:133)
我想了解每个事务隔离在表上执行的锁
例如,您有3个并发进程A,B和C. A启动事务,写入数据和提交/回滚(取决于结果)。 B只执行SELECT
语句来读取数据。 C读取和更新数据。所有这些过程都在同一个表T上工作。
WHERE aField > 10 AND aField < 20
,A插入数据,其中aField
值介于10和20之间,然后B再次读取数据并得到不同的结果。我想了解我们在哪里定义这些隔离级别:仅在JDBC / hibernate级别或在DB中
使用JDBC,您可以使用Connection#setTransactionIsolation
来定义它。
使用Hibernate:
<property name="hibernate.connection.isolation">2</property>
其中
Hibernate配置来自here(抱歉,它是西班牙语)。
顺便说一下,您也可以在RDBMS上设置隔离级别:
SET ISOLATION TO DIRTY READ
句。)等等...
答案 1 :(得分:6)
正如brb tea所说,取决于他们使用的数据库实现和算法:MVCC或两阶段锁定。
CUBRID(开源RDBMS)explains这两种算法的想法:
- 两相锁定(2PL)
第一个是当T2交易试图改变A记录时, 它知道T1交易已经改变了A记录和 由于T2交易等待T1交易完成 无法知道T1交易是否将被提交或滚动 背部。这种方法称为两相锁定(2PL)。
- 多版本并发控制(MVCC)
另一个是允许他们每个人进行T1和T2交易 有自己的更改版本。即使T1交易有 将A记录从1改为2,T1事务离开了 原始值1原样并写入T1事务版本 A记录为2.然后,以下T2事务更改A 记录从1到3,而不是从2到4,并写入T2 A记录的交易版本为3。
回滚T1事务时,如果是2,则无关紧要 T1事务版本,不适用于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中锁和隔离级别之间关系的具体示例(使用2PL,READ_COMMITTED_SNAPSHOT = ON时READ_COMMITED除外)
READ_UNCOMMITED:不发布共享锁以防止其他事务修改当前事务读取的数据。 READ UNCOMMITTED事务也不会被独占锁阻止,这会阻止当前事务读取已被修改但未被其他事务提交的行。 [...]
READ_COMMITED:
REPETEABLE_READ:共享锁定放在事务中每个语句读取的所有数据上,并保持到事务完成。
SERIALIZABLE:范围锁定位于与事务中执行的每个语句的搜索条件匹配的键值范围内。 [...]范围锁保持到交易完成。
答案 2 :(得分:4)
锁始终处于数据库级别: -
Oracle官方文档: - 为了避免在事务期间发生冲突,DBMS使用锁定机制来阻止其他人访问事务正在访问的数据。 (请注意,在自动提交模式下,每个语句都是一个事务,只保留一个语句的锁定。)设置锁定后,它将一直有效,直到提交或回滚事务为止。例如,DBMS可以锁定表的一行,直到对其进行更新为止。此锁定的作用是防止用户获取脏读,即在永久化之前读取值。 (访问尚未提交的更新值被视为脏读,因为该值可能会回滚到其先前的值。如果读取稍后回滚的值,则会读取无效值。 )
如何设置锁定由所谓的事务隔离级别决定,其范围从完全不支持事务到支持执行非常严格的访问规则的事务。
事务隔离级别的一个示例是TRANSACTION_READ_COMMITTED,它不允许在提交值之前访问该值。换句话说,如果事务隔离级别设置为TRANSACTION_READ_COMMITTED,则DBMS不允许发生脏读。接口Connection包含五个值,表示可以在JDBC中使用的事务隔离级别。