笛里谁知壮士心,沙头空照征人骨。这篇文章主要讲述MYSQL事务超全知识总结#yyds干货盘点#相关的知识,希望能为你提供帮助。
@toc
- 为什么要有事务?
- 开启事务
start transaction;
- 提交或者回滚事务
commit; -- 提交事务,数据将会写到磁盘上的数据库 rollback; -- 数据回滚,回到最初的状态。
- 关闭自动提交功能
文章图片
- 演示事务
文章图片
1.2 代码演示 - 通过
conn.setAutoCommit(false);
来关闭自动提交的设置。 - 提交事务
conn.commit();
- 回滚事务
conn.rollback();
@Test public void testTransaction()Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try conn = JDBCUtil.getConn(); // 连接,事务默认就是自动提交的。关闭自动提交。 conn.setAutoCommit(false); String sql = "update account set money = money - ? where id = ?"; ps = conn.prepareStatement(sql); // 扣钱,扣ID为1的100块钱 ps.setInt(1, 100); ps.setInt(2, 1); ps.executeUpdate(); int a = 10 / 0 ; //加钱,给ID为2 加100块钱 ps.setInt(1, -100); ps.setInt(2, 2); ps.executeUpdate(); //成功: 提交事务。 conn.commit(); catch (SQLException e) try //事变:回滚事务 conn.rollback(); catch(SQLException e1) e1.printStackTrace(); e.printStackTrace(); finally JDBCUtil.release(conn, ps, rs);
1.3 事务的特性
- 原子性: 事务中包含的逻辑,不可分割。
- 一致性: 事务执行前后。数据完整性
- 隔离性: 事务在执行期间不应该受到其他事务的影响
- 持久性: 事务执行成功,那么数据应该持久保存到磁盘上
- 丢失更新: 如果多个线程操作,基于同一个查询结构对表中的记录进行修改,那么后修改的记录将会覆盖前面修改的记录,前面的修改就丢失掉了。
- 读未提交(Read uncommitted)
- 读已提交(Read committed)
- 可重复读(Repeatable read)
- 可串行化(Serializable)
- 按效率划分,从高到低
- 按拦截程度 ,从高到底
- mysql 默认的隔离级别是: 可重复读
- Oracle 默认的隔离级别是: 读已提交
√:可能出现 ×:不会出现 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
- 查看事务的隔离级别
-- 我安装的是MySQL8,原先的select @@tx_isolation; 不能用了 select @@transaction_isolation;
- 设置隔离级别为读未提交
-- read uncommitted 读未提交 set session transaction isolation level read uncommitted;
- 引发的问题:两个并发的事务," 事务A:更新" 、" 事务B:查询" ,事务B读取了事务A尚未提交的数据,即我们所说的脏读。
- 设置隔离级别为读已提交,可解决脏读。
-- read committed 读已提交 set session transaction isolation level read committed;
- 引发的问题:两个并发的事务," 事务A:查询" 、" 事务B:更新" ,事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变,即我们所说的不可重复读。
- 设置隔离级别为不可重复读,可解决不可重复读。
-- repeatable read 不可重复读 set session transaction isolation level repeatable read;
- 引发的问题:两个并发的事务," 事务A:更新" 、" 事务B:更新" ,事务A事先更新了数据,事务B紧接着又把更新了回来,并提交了事务,而事务A再次读取该数据时,发现数据没有发生改变,即我们所说的幻读。
- 设置隔离级别为可串行化,可解决一切问题。
-- serializable 可串行化 set session transaction isolation level serializable;
- 如果有一个连接的隔离级别设置为了串行化,那么谁先打开了事务,谁就有了先执行的权利,谁后打开事务,谁就只能等着,等前面的那个事务,提交或者回滚后,才能执行。这种隔离级别一般比较少用,容易造成性能上的问题,效率比较低。
- 解决丢失更新问题
- 悲观锁(Pessimistic Locking)
- 乐观锁(Optimistic Locking)
- 悲观锁原理:使用数据库内部锁机制,进行数据库表的锁定。就是在A管理员修改数据时,A管理员就将数据锁定,此时B管理员无法进行修改、查询。避免两个事务同时修改,也就解决了丢失更新问题。
- 在查询的时候,加入
for update
。 1.6.2 乐观锁
- 乐观锁原理:使用的不是数据库的锁机制,而是一个特殊标记字段,通过控制字段状态和内容得知数据是否发生了并发访问。进行数据修改时,数据库会检测version字段或者时间戳是否与原来的一致。若不一致,抛出异常,提醒更新。
- 要求程序员自己控制。可以通过给数据表添加自增的
version
字段或时间戳timestamp
。
推荐阅读
- kubernetes-部署longhorn
- 用pipeline来实现一个自由风格的构建
- 有关 CentOS 7 minimal 初始配置
- #yyds干货盘点#害,这恼人的BOM头
- #yyds干货盘点#--ELK-Elasticsearch介绍-1
- #yyds干货盘点#Windows Server之CA证书服务器看不到"web服务器"模板
- Ubuntu 18.04.1安装k8s的时候,提示缺少依赖包kubernetes-cni (= 0.7.5)
- 如何在WordPress分页上向上一个/下一个添加类( (paginate_links))
- 如何从WordPress中删除分类()