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

我已经读了大约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) 

以下是在事务隔离中可能出现的三种现象
脏读 – 没有锁
不可重复的读 – 没有肮脏读作为提交数据上的锁
幻像读取locking的SQL块(这是通过使用select查询select)

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

PS:我已经通过了oracle的隔离级别的链接,但是他们看起来很笨拙,并且谈论了数据库的具体情况

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

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

  • READ UNCOMMITTED – 没有锁在桌子上。 写入数据时,可以读取表格中的数据。 这意味着,写入数据(uncommited)和B可以读取这个uncommited数据并使用它(出于任何目的)。 如果A执行回滚,B仍然读取数据并使用它。 这是处理数据的最快但最不安全的方式,因为可能会导致在物理上不相关的表中发生数据漏洞(是的,两个表可以是逻辑上的,但在现实世界的应用程序中却没有物理相关)。
  • READ COMMITTED – locking已提交的数据。 您可以读取仅提交的数据。 这意味着,写入数据和B不能读取由A保存的数据,直到A执行提交。 这里的问题是,C可以更新在B上读取和使用的数据,并且B客户端将不具有更新的数据。
  • REPEATABLE READ – lockingsql块(通过使用select查询select)。 这意味着,B在某种情况下读取数据,即WHERE aField > 10 AND aField < 20 ,A插入的数据的字段值在10到20之间,然后B再次读取数据,得到不同的结果。
  • SERIALIZABLE – locking全表(在其上启动Select查询)。 这意味着,B读取数据,而没有其他事务可以修改表中的数据 。 这是处理数据的最安全但最慢的方式。 此外,由于简单的读取操作会locking表格 ,这可能会导致严重的生产问题:假设T表是发票表,用户X想知道当天的发票,而用户Y想要创build新的发票,所以当X执行发票的读取时,Y不能添加新的发票(当涉及金钱时,人们变得非常生气,特别是老板)。

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

使用JDBC,使用Connection#setTransactionIsolation定义它。

使用hibernate:

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

哪里

  • 1:读未读
  • 2:READ COMMITTED
  • 4:可重复读取
  • 8:可序列化

从这里取得Hibernateconfiguration(对不起,这是西class牙语)。

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

  • MySQL隔离级别 ,
  • SQL Server隔离级别
  • Informix隔离级别 (个人注意:我永远不会忘记SET ISOLATION TO DIRTY READ句子。)

并在…上…

锁始终在数据库级别进行: –

Oracle官方文档:为了避免事务中的冲突,DBMS使用locking机制来阻止其他人访问正在被事务访问的数据。 (请注意,在自动提交模式下,每个语句都是一个事务,锁只能为一个语句保留。)设置了锁后,它将一直保持有效,直到事务被提交或回退为止。 例如,DBMS可以locking表的一行,直到对其进行更新。 这个锁的作用是防止用户弄脏读取,也就是读取一个值,使其永久化。 (访问未提交的更新值被认为是脏读,因为该值可能会回滚到之前的值。如果读取的值稍后回滚,则会读取无效值。 )

如何设置locking取决于所谓的事务隔离级别,其范围可以从不支持事务到支持执行非常严格的访问规则的事务。

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

正如brb茶所说,取决于数据库的实现和他们使用的algorithm:MVCC或两阶段locking。

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

  • 两相locking(2PL)

第一个是当T2事务试图改变Alogging时,它知道T1事务已经改变了Alogging,并等到T1事务完成,因为T2事务不能知道T1事务是提交还是滚动背部。 这种方法被称为两相locking(2PL)。

  • 多版本并发控制(MVCC)

另一个是允许他们中的每一个,T1和T2交易,都有自己的改变版本。 即使T1事务将Alogging从1更改为2,T1事务仍保留原始值1,并写入Alogging的T1事务版本为2.然后,以下T2事务更改Alogging从1到3,而不是从2到4,并且写道Alogging的T2事务版本是3。

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

MVCC允许以增加内存开销(因为它必须保持不同版本的相同数据)和计算(在REPETEABLE_READ级别上,不能丢失更新,所以它必须检查数据的版本,如Hiberate与Optimisticklocking )。

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

  • 读取数据时是否进行locking,请求何种types的锁。

  • 读锁持续了多久。

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

    • 阻塞,直到行上的排他锁被释放。

    • 检索在语句或事务开始时存在的行的提交版本。

    • 阅读未提交的数据修改。

select事务隔离级别不会影响为保护数据修改而获取的锁。 事务总是获得它所修改的任何数据的排他锁,并持有该锁直到事务完成,而不pipe为该事务设置的隔离级别。 对于读取操作,事务隔离级别主要定义了防止其他事务进行修改的影响的级别。

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

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

  • READ_UNCOMMITED:不发出共享锁以防止其他事务修改当前事务读取的数据。 READ UNCOMMITTED事务也不会被独占锁阻止,这会阻止当前事务读取已被修改但不被其他事务处理的行。 […]

  • READ_COMMITED:

    • 如果READ_COMMITTED_SNAPSHOT设置为OFF(缺省值):使用共享锁来阻止其他事务在当前事务正在执行读取操作时修改行。 共享锁还会阻止读取由其他事务修改的行的语句,直到其他事务完成。 行锁在下一行被处理之前被释放。 […]
    • 如果READ_COMMITTED_SNAPSHOT设置为ON,则数据库引擎使用行版本控制来为每个语句显示数据在事务开始时存在的事务一致快照。 不用锁来保护数据免受其他事务的更新。
  • REPETEABLE_READ:共享锁放置在事务中每个语句读取的所有数据上,并保持到事务完成。

  • SERIALIZABLE:范围locking放置在与事务中执行的每个语句的search条件相匹配的键值范围内。 […]范围locking一直持续到事务完成。