事务管理
引入:
需求:从 zhangsan 的账户转账 1000 给 lisi
出现问题:如果 zhangsan 的余额扣掉 1000,但是 lisi 的余额并没有加上 1000,此时转账是失败,
但是我们也无法通过代码让 zhangsan 的钱还原
此时我们要想保证转账失败失败的时候,张三的钱能够恢复原状,我们需要使用事务
概述
事务是指逻辑上的一组操作(对于数据库来说,就是多条 SQL语句),这一组操作中包含单个操作要么 全部成功,要么全部失败
MySQL管理事务
MySQL中的事务是默认提交的(数据永久改变),每执行一条SQL语句,就会提交一个事务,且不能撤回更改
我们可以通过MySQL开启一个事务(可以回退操作)
START TRANSACTION; -- 开启事务
UPDATE 表名 SET money=money-1000 WHERE name=’zhangsan’; --模拟张三转账
1000
ROLLBACK; --假如转账失败,可以通过rollback语句来回退操作,还原张三余额
另外我们可以通过以下语句来关闭自动提交
(相当于每次执行SQL语句前,都自动开启了一个事务 -- START TRANSACTION)
SHOW VARIABLES LIKE ‘%commit%’; -- 查看MySQL自动提交变量
SET AUTOCOMMIT=OFF; -- 关闭自动提交,默认为ON 如要提交执行COMMIT;
JDBC管理事务
/*
利用 JDBC 实现转账业务
JDBC 操作事务:
Connection 中的方法:
setAutoCommit(false):关闭数据库的自动提交,相当于 START TRANSACTION;
commit():将操作更改的数据永久应用到数据库
rollback():回滚操作,将数据恢复到执行 SQL 语句之前的状态
*/
事务四大特性
1.原子性:事务中的操作是不可分割的,要么都成功,要么都失败
2.一致性:保证数据完整性,例如:删除种类表 id=3 的种类,但是我们没有删除商品表中 cid=3 对应的商品信息 此时商品表中依赖 cid=3 种类信息丢失,破坏数据一致性,我们需要先删除商品表中 cid=3 的所有商品信息,然后在删除种类表中 id=3 的种类信息
3.隔离性:多个事务操作一条数据记录,事务之间应该相互隔离,不受影响
4.持久性:事务一旦提交(commit),数据将将永久改变,不能恢复
可能产生的安全问题
多个事务操作数据库同一份数据,如果不考虑隔离性会引发一些安全性问题:
1.脏读: 一个事务读到了另一个事务未提交的数据
2.不可重复读: 一个事务读到了另一个事务已经提交的 update 语句的数据,导致一个事务中出现多次查询,查询结果结果不一致
3.虚读: 一个事务读到了另一个事务已经提交的 insert 语句的数据,导致一个事务中出现多次查询,查询结果结果不一致
需要使用数据库隔离级别来解决上面三种问题:
1.read uncommitted : 未提交读 脏读,不可重复读,虚读都有可能发生
2.read committed : 已提交读 避免脏读, 不可重复读,虚读都有可能发生
3.repeatable read: 可重复读 避免脏读,不可重复读,虚读有可能发生
4.serializable: 串行化 避免脏读,不可重复读,虚读
导致一个事务未执行完,其它事务无法执行
从上到下,安全性依次递增,效率依次递减
MySQL 数据库默认隔离级别:repeatable read