开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第16天,点击查看活动详情
锁与事务
上一节介绍了数据库的索引,本节将围绕数据库的锁与事务。包括不同粒度的锁,比如全局锁,表级锁和行级锁。事务包括四种不同的事务等级。
锁
锁是协调多个进程或线程访问同一资源的方式。在数据库中自带有不同粒度的锁。
全局锁
一般在需要备份全局数据使用全局锁。
加锁:flush tables with read lock
释放锁:unlock tables
表锁
1.表锁:最常用的,也就是自己手动加锁的方式,一般用于整表迁移的场景
加读锁:lock table xxx read
当前和其它Session都可以读这张表
当前Session插入或更新会报错,其它Session则会等待
加写锁:lock table xxx write
当前Session可以对表进行增删改查,其它Session则会被阻塞
2.元数据锁(MDL):这种锁是防止在CRUD时有线程对表结构进行修改。因此在CRUD时加的是MDL读锁,更改表结构时加MDL写锁。
3.意向锁:如果没有意向锁的话,我们要去加表排他锁就需要去遍历所有的行有没有排他锁,效率比较低。在给行加共享锁时加上表意向共享锁,给行加排他锁时加上表意向排他锁。意向锁之间不会冲突,也不会和行级的锁冲突,只会和表级的共享锁和排他锁冲突。
4.自增锁:当把某字段设置成自增就是靠自增锁实现的,自增锁不是在事务完成后释放,而是在插入语句后立即释放。由于这会阻塞其它事务的插入,因此可以采取更轻量级的方式,在值赋值完成后立即释放锁。
行锁
每次锁住一行数据。开销大,加锁慢,粒度最小因此并发度也是最高的。加行级锁需要满足几个条件,select语句的where字段需要是索引并且在语句后加上for update,并且行级锁只能在事务中使用。
Record Lock(记录锁):仅将该记录上锁。
Gap Lock(间隙锁):锁定一个范围,不包含记录本身,前开后开区间。
Next-Key Lock:对记录加锁时,加锁的基本单位,前开后闭区间。
在加临键锁时,不同的情况加的锁不同。
主键索引:如果是等值查询,命中纪录会加Record Lock,否则退化为Gap Lock。如果是范围查询,不同的版本不同8.0.17前加的是前开后闭区间的Next-Key Lock,往后的版本则是Gap Lock。
非主键唯一索引:如果是等值查询,for update命中纪录会在主键索引上加锁,for share在覆盖索引时仅在自己的索引上加锁。如果是范围查询,不是覆盖索引下,会对相应的范围加前开后闭区间锁,如果存在数据会在对应主键行加行锁。如果是覆盖索引,会对所有后闭区间内的所有主键行加行锁。
普通索引:由于不唯一,因此会向后查询知道查询到不为该值的记录,锁定该值区间,如果命中了数据会对对应的主键行加行锁。
事务
事务是由一组SQL语句组成的逻辑处理单元。事务通常含有四大属性,也就是常说的ACID
ACID
原子性(Atomicity):事务是一个原子操作,要么全部成功,要么全部失败。
一致性(Consistent):在事务的开始和结束,数据的状态要保持一致。也就是说所有相关的数据规则都应用于事务的修改,保证数据的完整性。
隔离性(Isolation):一个事务在提交修改前,对于其它事务是不可见的。
持续性(Durable):事务提交后,修改的数据将永久留在数据库中。
并发事务问题
同时并发事务处理会带来一系列的问题
脏读:一个事务读取到另一个事务尚未提交的数据。
不可重复读:一个事务前后读取的数据不一致。
幻读:事务A读取到了事务B的新增数据。
隔离级别
不同的隔离级别产生的并发事务问题不同
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交(Read Uncommitted) | 可能 | 可能 | 可能 |
| 读已提交(Read Committed) | 不可能 | 可能 | 可能 |
| 可重复读(Repeatable Read) | 不可能 | 不可能 | 可能 |
| 串行化(Serializable) | 不可能 | 不可能 | 不可能 |
MySQL的默认隔离机制是RR可重复度读
查看当前数据库的隔离级别:show variables like 'tx_isolation';
设置事务隔离级别:set tx_isolation = 'REPEATABLE-READ';
set session transaction isolation level read committed;
总结
本节介绍了数据库不同粒度的锁,以及四种数据库的隔离级别,不同的隔离级别可能产生的问题也不一样,下一节将介绍数据库隔离级别的实现方式,以及三种不同的数据库日志undo,redo和binlog。
感谢观看!