1. 事务的 ACID 特性?
-
事务是对数据库中一系列操作进行统一的回滚或者提交的操作,主要用来保证数据的完整性和一致性。
-
原子性(Atomicity):
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。 -
一致性(Consistency): 事务开始前和结束后,数据库的完整性约束没有被破坏。比如 A 向 B 转账,不可能 A 扣了钱,B
却没收到。 -
隔离性(Isolation):
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如
A 正在从一张银行卡中取钱,在 A 取钱的过程结束前,B 不能向这张卡转账。 -
持久性(Durability):
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
2. 事务并发会造成的问题?
-
脏读:事务 A 读取了事务 B 更新的数据,然后 B 回滚操作,那么 A 读取到的数据是脏数据
-
不可重复读:事务 A 多次读取同一数据,事务 B 在事务 A 多次读取的过程中,对数据作了更新并提交,导致事务 A
多次读取同一数据时,结果因此本事务先后两次读到的数据因更新结果会不一致。不可重复读的重点是修改。同样的条件, 你读取过的数据,
再次读取出来发现值不一样了 -
幻读:幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。幻读的重点在于新增或者删除。同样的条件, 第 1
次和第 2 次读出来的记录数不一样
3. 事务的隔离级别?
-
Read uncommitted:读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。会造成脏读。
-
Read committed:读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。若有事务对数据进行更新
-
(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但会造成不可重复读。
-
Repeatable read:重复读,就是在开始读取数据(事务开启)时,不再允许修改操作在同一个事务里,SELECT
的结果是事务开始时时间点的状态,因此,同样的 SELECT 操作读到的结果会是一致的。但是,会有幻读现象。 -
Serializable 序列化,Serializable
是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
4. 说一下乐观锁和悲观锁?说一下 mysql 的行锁和表锁?
- 悲观锁: 先获取锁,再进行业务操作。即 “悲观”
的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的
select … for update 操作来实现悲观锁。 - 乐观锁的特点先进行业务操作,不到万不得已不去拿锁。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么当前正在提交的事务会进行回滚。
- 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
- 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
行锁又分为读锁和写锁:
-
共享锁:也称读锁或 S 锁。如果事务 T 对数据 A 加上共享锁后,则其他事务只能对 A 再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据。
-
排它锁:也称独占锁、写锁或 X 锁。如果事务 T 对数据 A 加上排它锁后,则其他事务不能再对 A 加任何类型的锁。获得排它锁的事务即能读数据又能修改数据。
5. 事务的隔离级别和加锁的关系?
-
读未提交
事务读不阻塞其他事务读和写,事务写阻塞其他事务写但不阻塞读。
可以通过写操作加 “持续 - X 锁” 实现。 -
读已提交
事务读不会阻塞其他事务读和写,事务写会阻塞其他事务读和写。
可以通过写操作加 “持续 - X” 锁,读操作加 “临时 - S 锁” 实现。 -
可重复读
事务读会阻塞其他事务事务写但不阻塞读,事务写会阻塞其他事务读和写。 可以通过写操作加 “持续 - X” 锁,读操作加 “持续 -
S 锁” 实现。 -
串行化
“行级锁” 做不到,需使用 “表级锁”。