MySQL事务和锁

1.事务

1.1 事务的概念

事务是一组连续的操作集合,MySQL中默认AUTOCOMMIT是为1,也就是说每一次请求都是一个独立的事务,即改请求会被立即执行。以START TRANSACTION;或BEGIN开始一个事务,以COMMIT或者ROLLBACK结束一次事务。

1.2 事务的特性ACID

A 原子性

一个事务必须保证其中的操作要么全部执行,要么全部回滚,不可能存在只执行了一部分这种情况出现。

C 一致性
数据必须保证从一种一致性的状态转换为另一种一致性状态。
比如上一个事务中执行了第二步时系统崩溃了,数据也不会出现bill的账户少了100块,但是tim的账户没变的情况。要么维持原装(全部回滚),要么bill少了100块同时tim多了100块,只有这两种一致性状态的。

I 隔离性
在一个事务未执行完毕时,通常会保证其他事务无法看到这个事务的执行结果。

D 持久性
事务一旦commit,则数据就会保存下来,即使提交完之后系统崩溃,数据也不会丢失。

2.隔离级别

2.1 读未提交

会出现脏读。一事务未提交的中间状态的更新数据被其他会话读取到。

2.2 读已提交

解决脏读,会出现幻读。会话A事务中执行一次查询,然后会话A新插入一行满足A事务查询条件的记录,此时A事务重新查询时,导致A事务两次读取的数据不一致。

2.3 可重复读

解决幻读。

2.4 串行化

最强的隔离级别,通过给事务中每次读取的行加锁,写加写锁,可能会导致大量超时以及锁争用问题。

3.锁

3.1 共享锁(S)

共享锁也称为读锁,读锁允许多个连接可以同一时刻并发的读取同一资源,互不干扰

3.2 排它锁(X)

排他锁也称为写锁,一个写锁会阻塞其他的写锁或读锁,保证同一时刻只有一个连接可以写入数据,同时防止其他用户对这个数据的读写。

4.避免死锁

如何避免使用行锁FOR UPDATE时导致死锁问题:

  1. 以固定的顺序访问数据,例如两个更新数据的事务,事务A更新数据的顺序为1,2;事务B更新数据的顺序为2,1。这样更可能会造成死锁。
  2. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。
  3. 为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁,死锁的概率大大增大。