正如brb tea所说,取决于他们使用的数据库实现和算法:MVCC或两阶段锁定。
CUBRID(开源RDBMS) 说明 这两种算法的想法:
两相锁定(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)。
第一个是T2事务尝试更改A记录时, 它知道T1交易已经改变了A记录和 由于T2交易等待T1交易完成 无法知道T1交易是否将被提交或滚动 背部。该方法称为两相锁定(2PL)。
另一个是允许他们每个人进行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锁定 )。
在2PL 事务隔离级别控制以下内容 :
是否在读取数据时执行锁定以及请求的锁定类型。 读锁的持有时间。 是否读取操作引用由另一个事务修改的行: 阻止,直到释放行上的独占锁定。 检索语句或事务开始时存在的行的已提交版本。 阅读未提交的数据修改。 选择事务隔离级别不会影响锁定 获得以保护数据修改。交易总是得到 对其修改的任何数据进行独占锁定并保持锁定直到 无论为哪个隔离级别设置,事务都会完成 那笔交易。对于读操作,事务隔离级别 主要定义保护水平免受影响 其他交易所做的修改。 的 较低的隔离级别增加了许多用户访问的能力 数据同时增加并发数量 效果 强> 用户可能会使用脏读或丢失的更新 遭遇。
是否在读取数据时执行锁定以及请求的锁定类型。
读锁的持有时间。
是否读取操作引用由另一个事务修改的行:
阻止,直到释放行上的独占锁定。
检索语句或事务开始时存在的行的已提交版本。
阅读未提交的数据修改。
选择事务隔离级别不会影响锁定 获得以保护数据修改。交易总是得到 对其修改的任何数据进行独占锁定并保持锁定直到 无论为哪个隔离级别设置,事务都会完成 那笔交易。对于读操作,事务隔离级别 主要定义保护水平免受影响 其他交易所做的修改。
的 较低的隔离级别增加了许多用户访问的能力 数据同时增加并发数量 效果 强> 用户可能会使用脏读或丢失的更新 遭遇。
中的锁和隔离级别之间关系的具体例子 SQL Server (在READ_COMMITTED_SNAPSHOT = ON的READ_COMMITED上使用2PL除外)
READ_UNCOMMITED:不发布共享锁以防止其他事务从修改当前事务读取的数据。 READ UNCOMMITTED事务也不会被独占锁阻止,这会阻止当前事务读取已被修改但未被其他事务提交的行。 [...]
READ_COMMITED:
REPETEABLE_READ:共享锁定放在事务中每个语句读取的所有数据上,并保持到事务完成。
SERIALIZABLE:范围锁定位于与事务中执行的每个语句的搜索条件匹配的键值范围内。 [...]范围锁保持到事务完成。
锁始终在DB级别进行: -
Oracle官方文档: - 为了避免在事务期间发生冲突,DBMS使用锁定机制来阻止其他人访问事务正在访问的数据。 (请注意,在自动提交模式下,每个语句都是一个事务,只保留一个语句的锁定。)设置锁定后,它将一直有效,直到提交或回滚事务为止。例如,DBMS可以锁定表的一行,直到对其进行更新为止。此锁定的作用是防止用户获取脏读,即在永久化之前读取值。 (访问尚未提交的更新值被视为脏读,因为该值可能会回滚到其先前的值。如果读取稍后回滚的值,则会读取无效值。 )
如何设置锁定由所谓的事务隔离级别决定,其范围从完全不支持事务到支持执行非常严格的访问规则的事务。
事务隔离级别的一个示例是TRANSACTION_READ_COMMITTED,它不允许在提交之前访问值。换句话说,如果事务隔离级别设置为TRANSACTION_READ_COMMITTED,则DBMS不允许发生脏读。接口Connection包含五个值,表示可在JDBC中使用的事务隔离级别。
的 我想明白 强> 锁定每个事务隔离对表进行的操作
例如,您有3个并发进程A,B和C.A启动事务,写入数据和提交/回滚(取决于结果)。 B只是执行一个 SELECT 声明读取数据。 C读取和更新数据。所有这些过程都在同一张桌子上工作。
SELECT
WHERE aField > 10 AND aField < 20
aField
的 我想明白 强> 我们定义这些隔离级别:仅在JDBC / hibernate级别或在DB中
使用JDBC,您可以使用它来定义它 Connection#setTransactionIsolation 。
Connection#setTransactionIsolation
使用Hibernate:
<property name="hibernate.connection.isolation">2</property>
哪里
Hibernate配置取自 这里 (对不起,用西班牙语)。
顺便说一句,您也可以在RDBMS上设置隔离级别:
SET ISOLATION TO DIRTY READ
等等...