9.1 事务概念
事务是指对数据库进行的一批操作,由一个或多个相关的增/删/改/查语句组成。在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
基本操作:
start transaction:开始一个事务
savepoint 保存点名:设置保存点
rollback to 保存点名:回退事务
RELEASE SAVEPOINT保存点名:删除保存点,当没有指定的保存点时,执行该语句会抛出一个异常
rollback:回退全部事务
commit:提交事务,所有的操作生效,不能回退,同时删除保存点
SET TRANSACTION :设置事务的隔离级别
只读事务:表示在事务中执行的是一些只读操作,如查询,但是不会做insert、update、delete操作(执行会报错),数据库内部对只读事务可能会有一些性能上的优化。
start transaction read only;
事务的ACID特性:一致性是最终目的
原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency):一个事务必须使数据库从一个一致性状态变换到另一个一致性状态。从实际的业务逻辑上来说,一致性要求最终结果是对的、是跟程序员的所期望的结果完全符合的。
隔离性(Isolation):多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability):一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。
SET 改变 MySQL 的自动提交模式:
SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1 开启自动提交
9.2 事务和锁
当执行事务操作时,mysql会在表上加锁,防止其它用户改表的数据。
9.3 回退事务
保存点:是事务中的点,用于取消部分事务,就像存了个历史版本。
当执行回退事务时,通过指定保存点可以回退到指定的点。指定保存点之后的保存点会被自动删除
当结束/提交事务时(commit),会自动的删除该事务所定义的所有保存点。
9.4 提交事务
当执行了commit语句后,会确认事务的变化、结束事务、删除保存点、释放锁,数据生效,其它会话[其他连接]将可以查看到事务变化后的新数据[所有数据就正式生效] 。
细节:
如果不开始事务,默认情况下,DML操作是自动提交的,不能回滚
如果开始一个事务,但没有创建保存点,也可以执行 rollback,默认回退到事务开始的状态
可以在这个事务中(还没有提交时),创建多个保存点
可以在事务没有提交前,选择回退到哪个保存点.
mysql的事务机制需要innodb的存储引擎才可以使用,myisam不好使
开始一个事务 start transaction, set autocommit=off;
9.5 事务隔离级别
多个连接开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个连接在获取数据时的准确性。
事务读取的是开启事务时数据库当下的状态!!
事务AB同时开启,即使A提交了事务,数据库有改动,B也不应该读取到改动后的数据,不应该受影响!
如果不考虑隔离性,可能会引发如下问题:
脏读:当一个事务读取另一个事务尚未提交的增/删/改时,产生脏读
不可重复读:同一查询在同一事务中多次进行,但由于其他提交事务所做的删/改,每次返回不同的结果集,此时发生不可重复读。
幻读:同一查询在同一事务中多次进行,由于其他提交事务所做的增操作,每次返回不同的结果集,此时发生幻读。
MySQL隔离级别定义了事务与事务间的隔离程度:从上至下隔离级别增强
隔离级别 |
脏读可能性 |
不可重复读可能性 |
幻读可能性 |
加锁读 |
READ-UNCOMMITTED读未提交 |
有 |
有 |
有 |
不加锁 |
READ-COMMITTED读已提交 |
无 |
有 |
有 |
不加锁 |
REPEATABLE-READ可重复读 |
无 |
无 |
有 |
不加锁 |
SERIALIZABLE可串行化 |
无 |
无 |
无 |
加锁 |
加锁:会发现当前有事务在操作但还没提交,会卡住,直到其他事务提交或超时退出。
默认可重复读,一般情况下不必修改。
# 查看当前会话的隔离级别
SELECT @@transaction_isolation;
# 查看系统当前隔离级别
SELECT @@global.transaction_isolation;
# 设置当前会话隔离级别
SET SEESION TRANSACTION ISOLATION LEVEL 隔离级别;
# 设置系统当前隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别;
# 全局修改,修改默认的隔离级别,在my.ini文件中添加
transaction_isolation = 隔离级别
事务还可能发生其他问题:
更新丢失:两个不同的事务(或者Java程序线程)在某一时刻对同一数据进行读取后,先后进行修改,导致第一次操作数据丢失(前者被后者覆盖)。
可重复读:一个事务操作中对于一个读取操作不管多少次,读取到的结果都是一样的。