mysql事务、隔离级别
一、事务
1.概念
往通俗的讲就是,事务就是一个整体,里面的内容要么都执行成功,要么都不成功。不可能存在部分执行成功而部分执行不成功的情况。
2、事务ACID特性
- 原子性(Atomicity): 事务是一个不可分割的最小单位,要么全执行,要么全不执行。
- 一致性(Consistency):事务,在提交之前和提交之后,都必须处于,一致性状态。例如转账,A向B转了50块,A就少了50块,B多了50块,不会只有一方多了或一方少了。
- 隔离性(Isolation):并发事务之间的执行是相互隔离的,不互相影响。
- 持久性Durability):事务一旦提交,对数据库的数据的改变是永久的。
3、事务的基本操作
start transaction; -- 开启事务
update student set age = 52 where id = 1; -- SQL语句
-- rollback; 回滚语句,出错时对数据进行回滚。
commit;--提交事务,事务总是以回滚或提交结束
4、并发事务可能存在的问题
并发的事务中,mysql默认会通过加行锁的形式,防止并发对同一条数据进行修改。
在没有设置合适的隔离级别时,依然可能会出现以下问题:
- 脏读:一个事务读到了另一个事务还未提交的事务。
- 不可重复读:事务A读取了a数据,事务B对a数据进行了修改并提交,事务A再次读取a数据,读取到了B事务已经提交的a数据,这样事务A前后读取同一数据但结果不同,为不可重复读。
- 幻读:事务A根据条件a查询出了n条数据,事务B对数据库进行了增/删/改并提交事务,导致事务A再次根据条件a查出的数据与n不一致,为幻读。
5、隔离级别
为了避免以上出现的各种并发问题,我们就必然要采取一些手段。mysql数据库系统提供了四种事务的隔离级别,用来隔离并发运行各个事务,使得它们相互不受影响。
-- 查看事务的隔离级别
show variables like 'transaction_isolation';
-- 更改隔离级别
-- global为全局的隔离级别,后续新的事物都会采用改隔离界别
-- READ UNCOMITTED 读未提交
-- READ COMMITED 读已提交
-- REPEATABLE READ 可重复读
-- SERIALIZABLE 串行读
set global transaction isolation level read uncommitted;
- READ UNCOMITTED 读未提交
没解决任何并发事务的问题 - READ COMMITED 读已提交
解决脏读的问题 - REPEATABLE READ 可重复读
解决不可重复读的问题,为mysql默认的隔离级别 - SERIALIZABLE 串行读
解决幻读的问题,该隔离级别会导致性能问题,非必要不使用
6、死锁
多个并发事务之间,互相占有对方的需要资源,导致相互等待。下面客户端A和B中,A先获取id = 1的行锁,B先获取id = 2的行锁,A,B再往下执行都需等待对方释放锁,导致死锁的出现。默认情况下,mysql会将客户端B的事务进行回滚。(四条更新语句的执行顺序为:A1,B1,A2,B2)
客户端A
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update student set age = 1 where id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update student set age = 2 where id = 2;
Query OK, 1 row affected (9.30 sec)
Rows matched: 1 Changed: 1 Warnings: 0
客户端B
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> update student set age = 2 where id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> update student set age = 1 where id = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
mysql>