一、事务的四个特性
原子性(Atomicity,或称不可分割性)
一致性(Consistency)
隔离性(Isolation,又称独立性)
持久性(Durability)
二、事务的开启
默认设置下,事务都是自动提交的,即执行 SQL 语句后就会马上执行 COMMIT 操作。因此要显式地开启一个事务务须使用命令 BEGIN 或 START TRANSACTION,用来禁止使用当前会话的自动提交。
开启事务
BEGIN
事务回滚
ROLLBACK
提交事务
commit
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from book;
+----+--------------+----------------------+---------+
| id | title | url | user_id |
+----+--------------+----------------------+---------+
| 1 | 百度一下 | http://www.baidu.com | 1 |
| 2 | 腾讯视频 | http://qq.com | 1 |
| 3 | 王者荣耀 | http://q.com | 1 |
| 4 | 吃鸡 | http://chiji.com | 2 |
| 5 | qq音乐 | http://chiji.com | 2 |
| 6 | 酷狗音乐 | http://kugou.com | 3 |
| 7 | 网易游戏 | http:wy.com | 1 |
| 8 | 菠萝 | http:bol.com | 1 |
+----+--------------+----------------------+---------+
8 rows in set (0.00 sec)
mysql> INSERT into book (id,title,url,user_id) VALUES (null,"苹果","http:Apple.com",1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from book;
+----+--------------+----------------------+---------+
| id | title | url | user_id |
+----+--------------+----------------------+---------+
| 1 | 百度一下 | http://www.baidu.com | 1 |
| 2 | 腾讯视频 | http://qq.com | 1 |
| 3 | 王者荣耀 | http://q.com | 1 |
| 4 | 吃鸡 | http://chiji.com | 2 |
| 5 | qq音乐 | http://chiji.com | 2 |
| 6 | 酷狗音乐 | http://kugou.com | 3 |
| 7 | 网易游戏 | http:wy.com | 1 |
| 8 | 菠萝 | http:bol.com | 1 |
| 9 | 苹果 | http:Apple.com | 1 |
+----+--------------+----------------------+---------+
9 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.52 sec)
mysql> select * from book;
+----+--------------+----------------------+---------+
| id | title | url | user_id |
+----+--------------+----------------------+---------+
| 1 | 百度一下 | http://www.baidu.com | 1 |
| 2 | 腾讯视频 | http://qq.com | 1 |
| 3 | 王者荣耀 | http://q.com | 1 |
| 4 | 吃鸡 | http://chiji.com | 2 |
| 5 | qq音乐 | http://chiji.com | 2 |
| 6 | 酷狗音乐 | http://kugou.com | 3 |
| 7 | 网易游戏 | http:wy.com | 1 |
| 8 | 菠萝 | http:bol.com | 1 |
+----+--------------+----------------------+---------+
8 rows in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0?禁止自动提交
- SET AUTOCOMMIT=1?开启自动提交
- AUTOCOMMIT?的值是 ON,表示系统开启自动提交模式
查看?AUTOCOMMIT 当前事务是否开启
SHOW VARIABLES LIKE 'AUTOCOMMIT';
mysql> SET AUTOCOMMIT=0;
Query OK, 0 rows affected (0.10 sec)
mysql> select * from book;
+----+--------------+-----------------------+---------+
| id | title | url | user_id |
+----+--------------+-----------------------+---------+
| 1 | 百度一下 | http://www.baidu.com | 1 |
| 2 | 腾讯视频 | http://qq.com | 1 |
| 3 | 王者荣耀 | http://q.com | 1 |
| 4 | 吃鸡 | http://chiji.com | 2 |
| 5 | qq音乐 | http://chiji.com | 2 |
| 6 | 酷狗音乐 | http://kugou.com | 3 |
| 7 | 网易游戏 | http:wy.com | 1 |
| 8 | 菠萝 | http:bol.com | 1 |
| 10 | 小米 | http://www.xiaomi.com | 1 |
+----+--------------+-----------------------+---------+
9 rows in set (0.00 sec)
mysql> INSERT into book (id,title,url,user_id) VALUES (null,"华为","http://www.huawei.com",1);
Query OK, 1 row affected (0.00 sec)
mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)
三、事务的隔离级别
事务在高并发的情况下容易出现?脏读、缓度、?不可重复读
这里说一下锁更事务的隔离级别关系
锁就是为了实现事务的隔离性,加了对应的锁就防止其他事务同时对数据进行读写
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|
READ UNCOMITTED | √ | √ | √ | READ COMMITTED | × | √ | √ | REPEATABLE READ | × | × | √ | SERIALIZABLE | × | × | × |
四、Spring Boot 事务
一、隔离级别
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.transaction.annotation;
public enum Isolation {
// 默认值
DEFAULT(-1),
// 读未提交
READ_UNCOMMITTED(1),
// 读提交
READ_COMMITTED(2),
// 可重复度
REPEATABLE_READ(4),
// 串行化
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
Springboot已经帮我们封装好对底层数据库事务的操作,Spring Boot中推荐使用@Transactional注解来声明事务
添加完毕事务之后 程序如果报错的话数据就会进行回滚不会正常插入到数据库中;
SpringBoot 的隔离级别
DEFAULT ?:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是:?READ_COMMITTED ?。?
READ_UNCOMMITTED ?:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。?
READ_COMMITTED ?:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。?
REPEATABLE_READ ?:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。?
SERIALIZABLE ?:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。? 指定方法:通过使用?isolation ?属性设置,例如:@Transactional(isolation = Isolation.DEFAULT)
或者在yml里面设置全局
datasource:
tomcat:
default-transaction-isolation: 2
?如何选择隔离界别:前提重点是性能和一致性
大部分应用选择读写提交的方式设置事务,单纯设置隔离级别的话是没有解决一致性问题
二、传播行为
package org.springframework.transaction.annotation;
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
private final int value;
private Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
作用:很多用户都在应用系统中还信用卡的贷款,此时如果一个用户还款时发生异常会导致事务中的所有用户还款进行回滚;通过设置传播行为可以解决此问题。
默认传播方式:REQUIRED ?
REQUIRED ?:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。?
SUPPORTS ?:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。?
MANDATORY ?:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。?
REQUIRES_NEW ?:创建一个新的事务,如果当前存在事务,则把当前事务挂起。?
NOT_SUPPORTED ?:以非事务方式运行,如果当前存在事务,则把当前事务挂起。?
NEVER ?:以非事务方式运行,如果当前存在事务,则抛出异常。?
NESTED ?:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于?REQUIRED ?。? 指定方法:通过使用?propagation ?属性设置,例如:@Transactional(propagation = Propagation.REQUIRED)
三、Spring的事务和数据库的事务有什么区别?
Spring 事务是在数据库事务的基础上进行封装扩展
- 支持原有的数据库事务的隔离级别,加入了事务传播的概念
- 提供多个事务的合并或隔离的功能
- 提供声明式事务,让业务代码与事务分离,事务变得更易用 (AOP)
|