1.MyISAM与InnoDB关于锁方面的区别是什么
- MyISAM默认使用的是表级锁,不支持行级锁
- InnoDB默认用的是行级锁,也支持表级锁
MyISAM引擎
MyISAM引擎在进行查询的时候,会自动为表加上一个读锁,而对数据进行增删改的时候,会为我们操作的表,加上一个表级别的写锁,当读锁没有被释放,另外一个session想要对同一个表加上写锁,他就会被堵塞,直到所有的读锁被释放位置。
如何显示的为表加上读锁,如下:
释放锁:
- 读锁的别名:共享锁 --上了共享锁之后,依然支持上共享锁,但不支持上排它锁
- 写锁的别名:排它锁--上了排它锁之后,就不支持再上其他的锁
insert、delete、update都会上排它锁,对于select也可以上排它锁,如下:
当select操作上排它锁之后,其他session中的select也会被堵塞
InnoDB引擎
1.如下模拟两个session对同一行数据进行修改的情况:
两个session的修改语句如下:
执行结果发现,并没有出现第二个session在执行时出现堵塞的情况
InnoDB使用个是二段锁,即加锁和解锁是分两个步骤完成的,即先对同一个事务里的一批操作分别进行加锁,然后到commit的时候,在对事务里加上的锁进行统一的解锁,而当前的commit是自动提交的,所以看起来和MyISAM没哟太大的区别。
我们可以通过执行以下命令得到结论:
on:代表事务默认是自动提交的。
2.关闭自动提交(该设置只针对当前的session,而其他session仍然是自动提交的):
操作验证如下(前提的首要关闭自动提交):
1:其中一个session加上共享锁,执行如下语句:
2:在另外一个session中对同一行执行update操作
实验结果是第二个session中的操作能修改数据成功。
原因如下:
InnoDB对select进行了改进,不会默认上共享锁,第一个session中的select操作并没有对该行上锁,所以才导致更新是成功的。InnoDB引擎下如何显示的加共享锁,如下:
当在另外一个session中执行update操作的时候就会堵塞。
当sql语句不走索引时,整张表都会被锁住。
在session1中先执行以下sql
在session2中执行以下sql
虽然是针对不同行的操作,但由于sql没有走索引,整张表都会被锁住,第二个sql将会被阻塞。
DML锁:对数据进行操作的锁
DDL锁:对表结构进行改动的锁
悲观锁:对系统被外界(本系统当前其他事务+来自外部系统事务)修改持悲观态度,因此在数据处理过程中将数据处于锁定状态,依赖于数据库层提供的锁机制。
乐观锁:认为数据一般情况下不会造成冲突,所以在数据进行提交更新时,才会对数据冲突与否进行检测,如果发生冲突,则返回错误信息,让用户决定如何去做。不会使用数据库提供的锁机制。一般就是记录数据版本,使用版本号或者时间戳。
版本号(version字段):每次更新数据时,为了防止冲突,先去检查version再做更新,更新成功的话version+1
2.数据库事务的四大特性
ACID特性
Automic:事务包含的一组操作要么全执行,要么全不执行
Consistency:数据从一个一致性状态到达另一个一致性状态,数据满足完整性约束
Isolation:事务完成前数据的中间状态对其他事务是不可见的
Durabliity:保证提交的事务对数据库影响的永久性,需要REDO日志重启时恢复
3.事务隔离级别以及各级别下的并发访问问题
事务并发访问引起的问题以及如何避免
查看session事务隔离级别:select @@tx_isolation
设置当前session的事务隔离级别:set session transaction isolation level ...
- LU(Lost Update丢失更新):一个事物的更新覆盖了另一个事物的更新----现在主流数据库都为为我们自动加锁,mysql所有事务隔离级别在数据库上均可避免此类问题。
- DR(Dirty Read读取脏数据):一个事务读取了另一个事务更新却没有提交的数据----在RC(Read Commmited)隔离级别以上均可避免
set session transaction isolation level read commited
- NRR(Non-Repeatable Reads不可重复读):一个事务对同一个数据项的多次读取操作可能得到不同的结果,事务A多次读取同一数据,事务B在事务A读取数据的过程中,对数据进行了更新和提交,使得事务A多次读取时,得到的数据不一致----在RR(Repeatable Read)隔离级别以上均可避免,确保在同一事务中,对同一个数据的先后读取的结果是一样的。
set session transaction isolation level repeatable read
- (Phantom Reads幻读):事务A读取与搜索条件相匹配的若干行,事务B以插入或删除行等方式来修改事务A的结果集,导致事务A看起来像出现幻觉一样----S(Serializable)隔离级别可以避免
set session transaction isolation level serializable
4.InnoDB可重复读隔离级别下如何避免幻读
- 表象:快照读(非阻塞读)----伪MVCC
- 内在:next-key锁(行锁+gap锁)
什么是当前读和快照读
当前读:加了锁的增删改查
快照读:不加锁的增删改查
测试:4个session,1和2是RC,3和4是RR
session1和session2同时开启事务后分别执行以下:
在session1中执行快照读的结果
在session1中执行当前读的结果
结论1:在RC隔离级别下,快照读和当前读的效果一样
在session3和session4中进行同上面一样的操作
在session3中执行快照读的结果
在session4中执行当前读的结果
结论2:在RR隔离级别下,快照读有可能读到数据的是历史版本,第一次创建快照读的地方很关键,决定了后续快照读取出的数据的版本。
行锁:对单个行上的锁
Gap锁:加载插入数据空隙的锁,防止同一事物的两次当前读出现幻读的情况下
5.RC、RR级别下的InnoDB的非阻塞读如何实现