SQL 的四种隔离级别
-
READ UNCOMMITED(未提交读)
即使事务没有提交,对其他事务依然是可读的,也称之为脏读。
-
READ COMMITED(提交读)
大多数数据库系统的默认隔离级别(Mysql 不是)。在事务提交前,所做的任何修改对其他事务均不可见,也称之为不可重复读(norepeatable read),因为两次查询可能得到不同的结果。
-
REPEATABLE READ(可重复读) —— Mysql 默认
可解决脏读问题,但是无法解决幻读(Phantom Read)问题(a 事务在读取某范围的记录时,b 事务又在该范围插入了新的记录,导致 a 再次读取的时候产生幻行,InnoDB 和 XtraDB 通过多版本并发控制来解决幻读问题)。
-
SERIALIZABLE(可串型化)
SQL 的最高隔离级别。强制事务串行执行,以此来避免幻读问题。SERIALIZABLE 会在读取的每条记录上都加锁,所以可能导致锁争用和超时问题。
隔离级别 | 脏读可能性 | 不可重复读可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
READ UNCOMMITED | YES | YES | NO | NO |
READ COMMITED | NO | YES | YES | NO |
REPEATABLE READ | NO | NO | YES | NO |
SERIALIZABLE | NO | NO | NO | YES |
死锁
解决死锁的两种方式
- 检测循环依赖,并立即返回错误(比如 InnoDB)
- 设定锁等待时间
死锁产生的原因
- 数据冲突
- 存储引擎的实现方式导致
事务
事务日志可以提高事务的效率。存储引擎在修改表的数据时,只需修改其在内存中的拷贝,再把修改行为记录持久在硬盘中。事务日志采用追加的方式,因此操作的是一小块 I/O 区域,可以提高速度,并且内存中修改的记录可以缓慢的持久到硬盘中。
存储引擎会自动恢复因为系统奔溃而出现的已经修改,但是尚未写回磁盘的数据。
Mysql 的事务默认采用自动提交的方式:
show variables like 'autocommit'
使用 Mysql
命令行可以启用/禁用自动提交
当 AUTOCOMMIT=0
时,所有的操作都在同一个事务里执行,直到显示执行 commit
或者 rollback
,该事务结束,同时又开启了另一个新事务。
而对于非事务类型的表,比如 MyISAM
或者 内存表,修改 autocommit
不会有任何影响,相当于一直开启自动提交事务的状态。