MySQL事务处理与并发控制( 三 )


写偏序的特征:
这种异常称为写偏序 。它既不是脏写 , 也不是丢失更新 , 因为这两个事务正在更新两个不同的对象(Alice和Bob各自的待命记录) 。
由上可见:如果不进行并发控制 , 会使得多个并发执行的事务造成各种各样的问题 , 因此需要并发控制技术 。
那么是不是只要简单的对各个事务进行排队 , 并一个接一个的执行就可以了呢?是的 , 这样的确可以 , 但是 , 这样会使得数据库的性能非常差 , 为了提高数据库的性能 , SQL标准定义了四种隔离级别 , 这四种隔离级别分别在三种数据读异常前后插入 , 对应的解决了读异常的发生 。
1.4 在正确性和效率之间做权衡为了提高数据库的效率 , 同时兼顾正确性 , SQL标准定义了四种隔离级别 , 分别解决各种读数据异常:
这四种隔离级别如下:

  • 1 未提交读(READ UNCOMMITTED):一个事务在执行过程中可以看到其他事务“尚未提交”的修改(包含更新和插入) , 该隔离级别允许脏读 , 在实际应用中没有实用价值 。
  • 2 已提交读(READ COMMITTED):一个事务在执行过程中可以看到其他事务“已经提交”的修改(包含更新和插入) 。该隔离级别下 , 允许不可重复读发生 , 不允许脏读 。
  • 3 可重复性读(REPEATABLE READ):一个事务在执行过程中可以看到其他事务已经提交的新插入的元组 , 但是不能看到其他事务对已有元组的更新 。允许幻读(范围查询时会出现) 。
  • 4 可串行化(SERIALIZABLE):看上去就是一个事务接着一个事务的串行执行 , 不会出现任何不一致 。
实际应用中 , 已提交读和可重复度比较常用(MySQL默认情况下为可重复性读) 。
四种隔离级别都不允许脏写和丢失更新发生 。
2 ACID的实现技术在第一节 , 学习了数据库的基本概念 , 特别是事务及其特性 , 本节梳理一下实现事务和ACID特性的技术 。
2.1 实现原子性的技术
  1. 事务管理
begin;rollback;commit;
  1. 并发控制 , 避免并发事务之间的干扰
  2. 日志技术
  • redo日志:用于系统故障发生后的崩溃恢复 。
  • undo日志:用于故障恢复 。保证被aborted的事务一定是被aborted的 。
2.2 实现隔离性的技术并发控制技术 。主要包含:
  1. 加锁
  2. MVCC
2.3 实现 持久性的技术日志技术
  • redo日志:用于系统故障发生后的崩溃恢复 。
  • undo日志:用于故障恢复 。保证被aborted的事务一定是被aborted的 。
3 MySQL事务处理3.1 MySQL事务模型MySQL本质上是一个数据库软件的框架 , 支持插件化存储引擎 , MySQL的事务处理也与具体的存储引擎相关 , MySQL只是定义了事务处理的框架具体实现由存储引擎完成 。因此MySQL是否支持事务 , 是与存储引擎相关的 。从mysql-5.5.5开始,InnoDB作为默认存储引擎 , 该存储引擎是支持事务的 , 同时 , InnoDB也是MySQL做为OLTP场景标准的存储引擎 , 这里主要研究InnoDB的事务模型 。
MySQL的事务管理语句如下:
START TRANSACTION [transaction_characteristic [, transaction_characteristic] ...]transaction_characteristic: WITH CONSISTENT SNAPSHOT | READ WRITE | READ ONLYBEGIN [WORK]COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]SET autocommit = {0 | 1}以上这些语句提供了对事务的控制:

  • START TRANSACTION或BEGIN开始新的事务 。
  • COMMIT 提交当前事务 , 使其更改持久化 。
  • ROLLBACK 回滚当前事务 , 取消其更改 。
  • SET autocommit 禁用或启用当前会话的默认自动提交模式 。
  • 默认情况下 , MySQL在启用自动提交模式的情况下运行。这意味着只要执行更新(修改)语句 , MySQL就会将更新存储在磁盘上以使其永久保存 。更改无法回滚 。即:如果没有显示使用begin开启一个事务 , MySQL会隐式开启事务 , 并自动提交(SQL成功)或回滚(SQL失败) 。要为单个sql语句隐式禁用自动提交 , 请使用以下START TRANSACTION 语句:
START TRANSACTION;SELECT @A:=SUM(salary) FROM table1 WHERE type=1;UPDATE table2 SET summary=@A WHERE type=1;COMMIT;


推荐阅读