|
银行引用是事务的一个经典例子:假如银行有两张表,一张支票表,一张储蓄表,现在需要从Jones用户的支票账户转移200¥ 至储蓄账户,那么至少需要三步:
1. 检查Jones的支票账户余额是否大于200¥
2. Jones的支票账户-200¥
3. Jones的储蓄账户+200¥
上述三步可组成一个事务,当2、3步故障时,之前执行的操作会自动回滚,保证数据的一致性。
一、MySQL事务
MySQL事务是一组SQL语句或一个独立运行的工作单元并且满足ACID测试。
ACID测试:
A.atomicity,原子性,一个事务必须作为不可分割的最小单元,事务中的语句要么都执行成功,要么都执行失败。
C.consistency,一致性,数据库总是从一个一致性状态到另一个一致性状态(数据库的结果是一致的,所有事务中SQL语句共同修改后的结果)不可能因为系统奔溃出现上述支票表-200¥而储蓄表未+200¥,未提交的事务并不会保存至数据库中。
I. isolation ,隔离性,当前事务操作过程对于另一个线程事务的可见度,由隔离级别决定。
D. durability , 持久性 , 所有事务提交后都永久存放于数据库中。
隔离级别:
1. READ UNCOMMITTED (读未提交)
2. READ COMMITTED(读提交)
3. REPEATEABLE READ(可重复读)
4. SERIALIZABLE(序列化)
各个隔离级别可能产生的问题:
a.脏读,当前线程事务可以读取另一个线程事务未提交修改的数据。
b.不可重复读,事务提交前看到的数据不一致(别的线程修改提交); 线程1开启事务查询数据一个样,当线程2开启事务修改提交后,线程1再次查询发现数据修改(未提交),这就是不可重复读。
c.幻读, 可重复读级别通过MVCC机制保证事务提交前看到的数据都是一致的,但是又有一个新问题,当线程2修改完数据提交后,线程1看到的还是未修改前的原始数据,但实际底层数据已被更改,当线程1提交后发现数据改变,像幻觉一样,这就是幻读。
d.加锁读,SERIABLIZEBLE 为了解决幻读问题,当线程事务1查询数据,线程事务2修改数据会被锁住,因为数据具有不确定性。
事务相关的命令:
START TRANSACTION #开启事务
ROLLBACK #回滚事务
COMMIT #提交事务
SAVEPOINT>
ROLLBACK [WORK] TO [SAVEPOINT]>
RELEASE SAVEPOINT>
二、验证各事务隔离级别存在的问题:
1. READ UNCOMMITTED ——幻读
a.首先需要关闭事务自动提交功能
b.修改事务隔离级别为READ-UNCOMMITTED
c.开启事务功能
d.在一线程事务中修改数据但不提交,在另一线程查看数据已更改,这就是脏读,存在脏读就必然存在不可重复读、幻读问题。
2. READ COMMITTED——解决脏读,新问题:不可重复读
a. 修改事务级别为 READ-COMMITTED .
b. 开启事务,并在一线程中删除数据,另一线程查看发现数据已更改,这就是不可重复读。
3. REPEATEABLE READ——解决不可重复读,新问题:幻读
a.修改事务级别为REPEATABLE-READ
b.开启事务、并查询数据
c.线程2删除数据并提交,线程1事务未提交查看数据发现未改变(可重复读)
d.线程1提交事务发现数据已被改变,这就是幻读,事务提交前数据已被改变,但无法察觉到,事务未修改提交后却发现数据改变
4. SERIALIZABLE——解决幻读,新问题:加锁读
a.设置隔离级别为SERIALIZABLE,在线程1查看数据,线程2修改数据发现被锁住了,因为无法保证线程1事务提交后看到的数据一致,这就是加锁读
注意:需要先关闭autocommit=OFF ,并且需要在线程SELECT查看一次才能做出加锁效果。
|
|
|