文章目录
前言
当一个事务需求需要使用多个DML操作时,这个业务当成一个整体来处理。在处理的过程中,如果有失败或者异常。我们需要返回到业务开始的初始状态。如果处理成功,我们再将数据持久化存到磁盘中。这样的过程就是一个事务。事务具有原子性、一致性、隔离性、持久性。
简单来说,事务指的就是逻辑上的一组操作,组成这组操作的各个单元在执行的过程中要么全部成功要么全部失败。
使用关键词:commit、rollback、savepoint
一、事务的特性(ACID)
- 原子性(Atomicity)
指事务是一个不可分割的整体,事务的操作要么都发生,要么都不发生。 - 一致性(Consistency)
事务必须使数据库从一个一致性状态转换到另一个一致性状态。例如在转账前和转账后的总金额不变 - 隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离 - 持久性(Durability)
一个事务一旦被提交,它对数据库中的数据的改变就是永久性的,接下来即使数据库发生故障也不该对其数据有任何影响。
二、MySQL的事务
默认情况下,MySQL每执行一条SQL语句,都是一个单独的事务。 如果需要在一个事务中包含多条SQL语句,那么需要开启事务和结束事务。
-- 开启事务:
start transaction;
-- 结束事务:
commit
rollback;
事务开始的情况
- 连接到数据库上,并执行一条DML语句insert、update或delete
- 前一个事务结束后,又输入了另一条DML语句。
事务结束的情况
- 执行commit或rollback语句
- 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。
- 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。
- 断开与数据库的连接
- 执行了一条DML语句,该语句却失败了,在这种情况中,会为这个无效的DML语句执行rollback语句。
1.示例:sql语句实现事务支持
回滚
START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
SELECT * FROM account; UPDATE account SET balance=balance+10000 WHERE id=2;
ROLLBACK;
提交
START TRANSACTION;
UPDATE account SET balance=balance-10000 WHERE id=1;
SELECT * FROM account;
UPDATE account SET balance=balance+10000 WHERE id=2;
COMMIT;
三、多事务情况
1.脏读
事务A读取了事务B刚刚更新的数据,但是事务B回滚了。这样即导致事务A读取到的数据为脏数据,这就是脏读
2.不可重复读
事务A读取同一条数据俩次,但是在两次之间事务B对该记录进行了修改并提交,导致事务A两次读取的数据不一致。
与脏读的不同在于,脏读是事务A读取到事务B未提交的脏数据。不可重复读是事务A读取到事务B提交的数据。
3.幻读
事务A在对数据进行完查询后,事务B对其执行了新增数据的操作。事务A再进行查询数据的时候,发现无故新增了记录。这就是幻读。
4.幻读与不可重复读的比较
相同点:都是针对另外一个已经提交的事务而言。
不同点:不可重复读通常针对于同一条记录,而幻读是针对于多条记录。不可重复读重点在于update和delete,而幻读的重点在于insert
总结:数据库通过设置事务的隔离级别防止以上情况的发生。
四、隔离机制
1.隔离机制分类
- 未提交读(read uncommitted)
- 提交读(read committed)
- 可重复读(repeatable read)
- 序列化(Serializable)
1.1.1 未提交读
不做隔离控制,可以读到“脏数据”。可能发生不可重复读,也可能出现幻读。
1.1.2 提交度
不允许读取事务没有提交的数据。可以避免脏读的问题,但是可能发生不可重复读、幻读。这个隔离级别是大多数数据库(除MySQL)的默认隔离级别。
1.1.3 可重复读
为了避免提交读级别不可重复读的问题。在事务中对符合条件的记录上“排他锁”,这样其他事务不能对该事务操作的数据进行修改,可以避免不可重复读的问题产生。因为只对操作数据进行上锁的操作,所以当其他事务插入或删除数据时,会出现幻读的问题。这个隔离级别的MySQL的默认隔离级别。
1.1.4 序列化
在事务中对表上锁,这样在事务结束前,其他事务都不能对表数据进行操作(新增、删除和修改),这样避免了脏读、不可重复读和幻读,是最安全的隔离级别。但由于这种操作是堵塞的,所以会严重影响性能。
注意点:
- 隔离机制级别越高,数据越安全,性能越低
- 设置隔离级别必须在事务之前
2.mysql中隔离级别相关操作
查看当前事务隔离级别:SELECT @@TX_ISOLATION
更改当前事务隔离级别:SET TRANSACTION ISOLATION LEVEL 四个级别之一。
3.JDBC控制事务的隔离级别
Connection接口:
TRANSACTION_READ_UNCOMMITTED:可以发生脏读、不可重复读和幻读的常量
TRANSACTION_READ_COMMITTED:预防发生脏读的常量;不可重复读和幻读的可能发生
TRANSACTION_REPEATABLE_READ:预防发生脏读和不可重复读的常量;幻读可能发生
TRANSACTION_SERIALIZABLE:预防发生脏读、不可重复读和幻读的常量
设置方法:
Connection.setTransactionIsolation(int level);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/116591.html