默认采用行级锁
支持事务(transaction)
更新丢失(lost update)
当两个或多个事务选择同一行,然后基于最初选定的值更新该行时
由于每个事务都不知道其他事务的存在
就会发生丢失更新问题,最后的更新覆盖了由其他事务所做的更新。
脏读(dirty reads)
事务1正在对一条记录做修改
事务1完成并提交前,这条记录的数据就处于不一致状态
这时,事务2也来读取同一条记录,如果不加控制事务2读取了这些“脏”数据
并据此作进一步的处理,就会产生未提交的数据依赖关系。
不可重复读(non-repeatable reads)
一个事务在读取某些数据后的某个时间
再次读取以前读过的数据,却发现其读出的数据已经发生了改变或某些记录已经被删除了!
幻读(phantom reads)
一个事务按相同的查询条件重新读取以前检索过的数据
却发现其他事务插入了满足其查询条件的新数据
事务隔离级别 | 读数据一致性 | 严格 | 开销 | 速度 | 更新丢失 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|---|---|---|---|---|
未提交读(read uncommitted) | 最低级别,只能保证不读取物理上损坏的数据 | 不严格 | 开销小 | 最快 | 不出现 | 会出现 | 会出现 | 会出现 |
已提交读(read committed) | 语句级 | 一般 | 一般 | 一般 | 不出现 | 不出现 | 会出现 | 会出现 |
可重复读(repeatable read) | 事务级 | 一般 | 一般 | 一般 | 不出现 | 不出现 | 不出现 | 会出现 |
可序列化(serializable) | 最高级别,事务级 | 最严格 | 开销大 | 最慢 | 不出现 | 不出现 | 不出现 | 不出现 |
show status like "innodb_row_lock%";
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 0 |
| Innodb_row_lock_time_avg | 0 |
| Innodb_row_lock_time_max | 0 |
| Innodb_row_lock_waits | 0 |
+-------------------------------+-------+
5 rows in set (0.00 sec)
如果发现锁争用比较严重
如 Innodb_row_lock_waits 和 Innodb_row_lock_time_avg 的值比较高
可以通过查询 information_schema 数据库中相关的表来查看锁情况
或者通过设置 innodb monitors 来进一步观察。
use information_schema
select * from innodb_locks G;
通过设置 innodb monitors 观察锁冲突情况
create table innodb_monitor (a int) engine=innodb;
show engine innodb status G;
当前锁模式 | 当前锁模式 | 当前锁模式 | 当前锁模式 | |||
---|---|---|---|---|---|---|
锁类型 | 锁名 | 共享锁(X) | 意向共享锁(IX) | 排它锁(S) | 意向排它锁(IS) | |
请求锁模式 | 行锁 | 共享锁(X)—> | 冲突 | 冲突 | 冲突 | 冲突 |
请求锁模式 | 表锁(自动加的,不需要干预) | 意向共享锁(IX)—> | 冲突 | 兼容 | 冲突 | 兼容 |
请求锁模式 | 行锁 | 排它锁(S)—> | 冲突 | 冲突 | 兼容 | 兼容 |
请求锁模式 | 表锁(自动加的,不需要干预) | 意向排它锁(IS)—> | 冲突 | 兼容 | 兼容 | 兼容 |
加共享锁(S):select * from table_name where ... lock in share mode.
加排它锁(X): select * from table_name where ... for update.
看lock in share mode
看for update