1. -- 开启事务
  2. START TRANSACTION;
  3. -- 回滚事务
  4. ROLLBACK;
  5. -- 提交事务
  6. COMMIT;
  7. -- 查看事务提交方式
  8. SELECT @@AUTOCOMMIT; -- 1代表自动提交 0代表手动提交
  9. -- 修改事务提交方式
  10. -- 标准语法
  11. SET @@AUTOCOMMIT=数字;
  12. -- 修改为手动提交
  13. SET @@AUTOCOMMIT=0;
  14. -- 查看事务提交方式
  15. SELECT @@AUTOCOMMIT;

事务的四大特征(ACID)

  • 原子性(atomicity)
    • 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响
  • 一致性(consistency)
    • 一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态
    • 拿转账来说,假设张三和李四两者的钱加起来一共是2000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是2000,这就是事务的一致性
  • 隔离性(isolcation)
    • 隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
  • 持久性(durability)
    • 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作

      事务的隔离级别

  • 隔离级别的概念
    • 多个客户端操作时 ,各个客户端的事务之间应该是隔离的,相互独立的 , 不受影响的。
    • 而如果多个事务操作同一批数据时,则需要设置不同的隔离级别 , 否则就会产生问题 。
    • 我们先来了解一下四种隔离级别的名称 , 再来看看可能出现的问题
  • 四种隔离级别
    | 1 | 读未提交 | read uncommitted | | —- | —- | —- | | 2 | 读已提交 | read committed | | 3 | 可重复读 | repeatable read | | 4 | 串行化 | serializable |
  • 可能引发的问题
    | 问题 | 现象 | | —- | —- | | 脏读 | 是指在一个事务处理过程中读取了另一个未提交的事务中的数据 , 导致两次查询结果不一致 | | 不可重复读 | 是指在一个事务处理过程中读取了另一个事务中修改并已提交的数据, 导致两次查询结果不一致 | | 幻读 | select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入。或不存在执行delete删除,却发现删除成功 |
  1. -- 查询数据库隔离级别
  2. SELECT @@TX_ISOLATION;
  3. -- 修改数据库隔离级别
  4. SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串;
  5. -- 修改数据库隔离级别为read uncommitted
  6. SET GLOBAL TRANSACTION ISOLATION LEVEL read uncommitted;
  7. -- 查看隔离级别
  8. SELECT @@TX_ISOLATION; -- 修改后需要断开连接重新开

解决脏读

  1. -- 设置隔离级别为read committed
  2. set global transaction isolation level read committed;
  3. -- 开启事务
  4. start transaction;
  5. -- 转账
  6. update account set money = money - 500 where id = 1;
  7. update account set money = money + 500 where id = 2;
  8. -- 窗口2查看转账结果,并没有发生变化(脏读问题被解决了)
  9. -- 执行提交事务。
  10. commit;

解决不可重复读

  1. -- 设置隔离级别为repeatable read
  2. set global transaction isolation level repeatable read;
  3. -- 开启事务
  4. start transaction;
  5. -- 转账
  6. update account set money = money - 500 where id = 1;
  7. update account set money = money + 500 where id = 2;
  8. -- 窗口2查看转账结果,并没有发生变化
  9. -- 执行提交事务
  10. commit;
  11. -- 这个时候窗口2只要还在上次事务中,看到的结果都是相同的。只有窗口2结束事务,才能看到变化(不可重复读的问题被解决)

解决幻读

  1. /*
  2. 窗口1
  3. */
  4. -- 设置隔离级别为serializable
  5. set global transaction isolation level serializable;
  6. -- 开启事务
  7. start transaction;
  8. -- 添加一条记录
  9. INSERT INTO account VALUES (4,'赵六',1600);
  10. -- 查询账户表,本窗口可以查看到id4的结果
  11. SELECT * FROM account;
  12. -- 提交事务
  13. COMMIT;

隔离级别总结

|

隔离级别 名称 出现脏读 出现不可重复读 出现幻读 数据库默认隔离级别
1 read uncommitted 读未提交

| | 2 | read committed | 读已提交 | 否 | 是 | 是 | Oracle / SQL Server | | 3 | repeatable read | 可重复读 | 否 | 否 | 是 | MySQL | | 4 | serializable | 串行化 | 否 | 否 | 否 |

|