事物隔离机制

本文深入探讨了数据库并发操作中常见的异常情况,如更新丢失、脏读取、不可重复读取等,并介绍了四种标准SQL隔离级别如何有效避免这些并发问题。
数据库并发操作存在的异常情况:并发事物中

1.更新丢失(Lost update):两个事务更新一行数据,但是第二事务却中途失败退出,导致对数据两个修改都失效了,这是[size=large][/size][size=x-large][/size]系统没有执行任何锁操作,因此并发事务并没有被隔离开来
2.脏读取(Dirty Reads):一个事物开始读取了某行数据,但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险,很可能所有操作都被回滚
3.不可重复读取(Non-repeatable Reads):一个事务对同一行数据重复读取两次,但是却得到了不同结果。例如在两次读取中途,有另外一个事务对该行数据进行了修改并提交
4.两次更新问题(Second lost updates problem):无法重复读取特例,有两个并发事务同时读取同一行数据,然后其中一个对它进行修改提交,而另一个也进行了修改提交,这就会造成第一次写操作失效
5.幻读(Plantom Reads):事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据,这是因为在两次查询过程中有另外一个事务插入数据造成的。
为了避免上面的几种情况,在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同:

1.Read Uncommitted(未提交读):允许脏读取,但不允许更新丢失,如果一个事务已经开始写数据,则另外一个数据则不允许同时进行写操作,但允许其他事务读此行数据。此隔离级别可以通过“排他写锁”实现。事务隔离级别最低,仅可保证不读取物理损坏的数据。与Read Committed隔离级相反,它允许读取已经被其他用户修改但尚未提交确定的数据

2.Read Committed(提交读):允许不可重复读取,但不允许脏读取。这可以通过“瞬间共享读锁”和“排他写锁”实现,读取数据的事务允许其他事务继续访问该行数据,但是未提交写事务将会禁止其他事务访问该行。SQL Server默认的级别。在此隔离级下,Select命令不会返回尚未提交的数据,也不能返回脏数据
3.Repeatable Read(可重复读取):禁止不可重复读取和脏读取。但是有时可能出现幻影数据,这可能通过“共享读锁”和“排他写锁”实现,读取数据事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。在此隔离级别下,用Select命令读取的数据在整个命令执行过程中不会被更改。此选项会影响系统的效能,非必要情况最好不用此隔离级别
4.Serializable(可串行读):提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作事务访问到。事务隔离的最高级别,事务之间完全隔离。如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。
隔离级别 更新丢失 脏读取 重复读取 幻读

未提交读 N Y Y Y

提交读 N N Y Y

可重复读 N N N Y

串行 N N N N


-----------------------------来之网络 注意留看

事务并发处理(面试的意义更大)

a ) 事务 ACID

i atomic Consistency Itegrity Durability

原子 一致 独立 持久

b ) 事务并发时可能出现的问题

第一类丢失更新(Lost Update)

时间 取款事务A 存款事务B

T1 开始事务

T2 开始事务

T3 查询账户余额为1000元

T4 查询账户余额为1000元

T5 汇入100元把余额改为1100元

T6 提交事务

T7 取出100元把余额改为900

T8 撤销事务

T9 余额恢复为1000元(丢失更新)


ii dirty read 脏读

iii 不可重复读 non-repeatable read

Iv second lost update problem 第二类丢失更新(不可重复读的特殊情况)


V phantom read 幻读

c) 数据库的事务隔离机制

i 查看java.sql.Connection文档

ii 1 read - uncommitted 2: read - committed 4: repeatable read 8: serializable

a) 0001 0010    0100 1000

b) c R U    D

    c) c | u 0101

d) 0101 & 0001 == 0001

2 只要数据库支持事务,就不可能出现第一类丢失更新

3 read - uncommitted 会出现dirty read , phantom- read , non -repeatable read 问题

4 read - uncommitted 会出现 dirty read, 因为只有另一个事务提交才会读出来结果,但仍然会出现non- repeatable read , 和phantom- read

5 repeatable read

6 serial 解决一切问题

d) 设定hibernate 的事务隔离级别

i hibernate.connection.isolation = 2

ii 用悲观锁解决 repeatable read 的问题(依赖于数据库的锁)

1 select …… for update

2 load (** .class , i , LockMode. Update)

a) LockMode None 无锁的机制 ,Transaction结束时,切换到此模式

B)LockMode. read 在查询时hibernate 会自动获取锁

c ) LockMode.write insert update hibernate 会自动获取锁

d )以上3种锁的模式,是hibernate 内部使用的

e ) LockMode UPGRADE_ NOWAIT ORACLE 支持的锁的方式
MySQL的事务隔离机制是通过不同的隔离级别来控制事务并发执行时的数据可见性和一致性。隔离级别越高,事务之间的隔离程度越好,但性能开销也越大。SQL标准定义了四种常见的事务隔离级别,MySQL也支持这四种级别,并且每种级别都有其特定的实现原理。 ### 事务隔离级别 MySQL支持以下四种事务隔离级别: 1. **未提交读(Read Uncommitted)**:这是最低的隔离级别,允许一个事务读取另一个事务未提交的数据。这种级别可能导致脏读(Dirty Read),即读取到无效的或未提交的数据。 2. **提交读(Read Committed)**:该级别确保一个事务只能读取到其他事务已经提交的数据。它避免了脏读,但可能会出现不可重复读(Nonrepeatable Read)和幻读(Phantom Read)。 3. **可重复读(Repeatable Read)**:这是MySQL的默认隔离级别。它确保在同一个事务中多次读取同一数据时,结果是一致的,即使其他事务对数据进行了修改并提交。可重复读级别解决了不可重复读的问题,但可能仍然存在幻读。 4. **串行化(Serializable)**:这是最高的隔离级别,通过强制事务串行执行来避免所有并发问题。它完全隔离了事务之间的数据访问,避免了脏读、不可重复读和幻读,但性能开销最大。 ### 实现原理 MySQL的事务隔离机制主要依赖于其存储引擎(如InnoDB)来实现。InnoDB通过多版本并发控制(MVCC)和锁机制来实现不同级别的隔离性。 - **一致性读(Consistent Read)**:InnoDB使用多版本并发控制(MVCC)来提供一致性读。在`REPEATABLE READ`隔离级别下,事务中的所有一致性读都读取事务开始时的快照。而在`READ COMMITTED`隔离级别下,事务中的每个一致性读都会读取最新的快照版本。一致性读不会对表加锁,因此多个事务可以并发地修改数据。 - **锁机制**:InnoDB支持行级锁和表级锁。在`READ COMMITTED`和`REPEATABLE READ`级别,InnoDB使用行级锁来控制并发访问。在`SERIALIZABLE`级别,InnoDB会对所有读取操作加锁,从而强制事务串行化执行。 - **不可重复读与幻读**:在`READ COMMITTED`级别,由于每次一致性读都会刷新快照,因此可能会出现不可重复读。而在`REPEATABLE READ`级别,事务在整个生命周期内使用同一个快照,因此避免了不可重复读。至于幻读,在`REPEATABLE READ`级别,InnoDB通过间隙锁(Gap Lock)来防止其他事务插入新行,从而避免了幻读。 ### 隔离级别与并发问题的关系 | 隔离级别 | 脏读 | 不可重复读 | 幻读 | 丢失更新 | |---------------------|------|------------|------|----------| | 未提交读(Read Uncommitted) | 可能 | 可能 | 可能 | 可能 | | 提交读(Read Committed) | 不可能 | 可能 | 可能 | 可能 | | 可重复读(Repeatable Read) | 不可能 | 不可能 | 不可能 | 可能 | | 串行化(Serializable) | 不可能 | 不可能 | 不可能 | 不可能 | ### 设置隔离级别 在MySQL中,可以通过以下命令设置事务隔离级别: ```sql SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}; ``` 例如,将当前会话的隔离级别设置为`READ COMMITTED`: ```sql SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; ``` ### 总结 MySQL的事务隔离机制通过不同的隔离级别和实现原理来平衡数据一致性和并发性能。选择合适的隔离级别取决于具体的应用场景和对数据一致性的要求。较高的隔离级别可以提供更强的数据一致性,但可能会降低系统的并发性能[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值