隔离性的底层实现
其中事务的隔离性底层实现的原理是锁
锁的分类
按照数据操作的类型划分
- 读锁(共享锁):同一份数据,多个读操作可以同时进行,互不影响
- 写锁(排它锁):当前写操作还没完成,会阻断其他写锁和读锁
session1 加了读锁,当前session1不能读其他未加锁的表,而且不能插入或更新锁定的表。session2可以读或操作未加锁的表,但如果对加读锁的表进行操作,会一直等待获得锁(阻塞),直到上读锁的表释放锁之后,session2获得锁,操作完成。
按照数据操作的粒度划分
行锁(偏写)
锁定粒度最小,发生冲突率低,并发度也最高
偏向InnoDB存储引擎
锁定一行:在session1
select * from table where a = 8 for update
,此时锁定后只有session1自己可以继续,其他线程来操作数据会阻塞,直到session1 commit事务分析系统中行锁争夺情况
show status like 'innodb_row_lock%'
,其中有三个重要状态变量:innodb_row_lock_time_avg平均等待时长/innodb_row_lock_waits等待总次数/innodb_row_lock_time等待总时长
表锁(偏读)
- 读锁会阻塞写,但不会阻塞读。而写锁会把读和写都阻塞,MyISAM以读为主,故不能作为频繁更新操作,会导致阻塞。
锁的种类
- 乐观锁:每次取数据的时候都认为别人不会修改数据,所以不会上锁。但在更新时会判断别人有没有更新(版本号机制)
- 策略:通常在数据表最后加一个字段version。当A,B同时修改一条数据的不同字段(电话号码,微信号),(A比B快修改完提交)修改当A修改完一个事务,版本号+1,然后提交事务。接着B修改完提交的时候,B的版本号还是原来的1,但现在已经变成2了,B提交事务后立即报异常。得去数据库获取最新版本号,才能进行修改,+1后再提交。
- 用于多读类型,提高吞吐量
- 悲观锁:每次取数据的时候都会认为别人修改了数据,所以每次拿数据都会上锁。别人想拿到这个数据就会阻塞,直到拿到锁。
- 共享锁S(行锁)
- 排它锁X(行锁)
- 意向共享锁IS(表锁)
- 意向排它锁IX(表锁)
- 自增锁
- 间隙锁:当sql语句中用范围条件而不是相等条件检索数据,并请求共享或排它锁时,InnoDB会给符合条件的已有数据记录的索引项上锁。对于键值在条件范围内,但不存在的记录,成为“间隙”。InnoDB会给这个间隙上锁,称为“间隙锁”(Next-Key锁)