数据库锁模块
MyISAM与InnoDB关于锁方面的区别是什么?
- MyISAM默认用的是表级锁,不支持行级锁(在对数据库进行操作时只会锁住被操作的行)
- InnoDB默认用的是行级锁,也支持表级锁(在对数据库进行操作时会锁住整张表)
- MyISAM不支持事务
- InnoDB支持事务
数据库操作不走索引时使用的是表级锁
MyISAM
在该引擎下会默认添加表锁,当对数据进行select操作时会为表添加一个表级别的读锁;当进行update、insert和delete操作时会自动加上表级别的写锁。
适用场景
- 频繁执行全表count语句,MyISAM中有一个变量保存了整个表的行数
- 对数据进行增删改的频率不高(因为增删改会涉及到锁表操作),查询非常频繁
- 没有事务的场景
InnoDB
在该引擎下会默认使用的是行锁,行级锁与表级锁的共享性和排它性是一样的,只不过作用的范围不同,行级锁只作用于被上锁的行。
适用场景
- 数据增删改查都相当频繁
- 可靠性要求比较高,要求支持事务
数据库锁的分类
读锁
读锁又被称为共享锁,因为一个会话对数据库进行读操作不会阻塞其它会话的读操作,但是会阻塞其它会话的写操作。
在进行select操作的后面加上for update将会添加排它锁,加lock in share mode会添加共享锁
写锁
写锁又被称为排它锁,当一个会话给数据库加了写锁后会阻塞其它会话中所有的读和写操作。
显示添加读/写锁
lock tables TABLE_NAME read/write;
unlock tables 删除锁
页级锁
介于表级和行级锁之间,锁定位于被操作数据相邻的数据
意向锁
当事务A锁住了表中的某一行时,事务B如果想要申请整张表的写锁,这是因为事务A对数据行加了行锁,如果让B申请成功那么就会与A发生冲突。因此在给事务B分配表锁时需要判断当前数据库表有没有被其它事务加过行或者表锁,那么就需要进行如下判断:
1:判断表是否已被其他事务用表锁锁表
2:判断表中的是否有任意一行已被行锁锁住。
这样的话在第2步中需要对整张表中记录进行判断,效率比较低。于是就有了意向锁,在意向锁存在的情况下,任何事务对表或者行进行上锁前都必须先获取意向锁,有了意向锁,上面的检查过程就变为:
1:不变
2:获取表的意向锁
申请意向锁的动作是数据库完成的,事务进行上锁时数据库会自动先申请表的意向锁,不需要我们程序员使用代码来申请
悲观锁
当我们要对一个数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制。
乐观锁
乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。
事务的ACID
原子性(Atomicity):指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生
一致性(Consistency):事务前后数据的完整性必须保持一致,可类比能量守恒定律
隔离性(Isolation):指多个用户并发访问数据库时,数据库为每个用户开启事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
持久性(Durability):指一个事务一旦被提交,他对数据库中数据的改变是永久性的,接下来即使数据库发生故障也不应该对其有影响
事务隔离级别以及各级别下的并发访问问题
查看会话的事务隔离级别select @@tx_isolation
设置会话的隔离级别set session transaction isolation level read uncommitted
事务隔离级别越高,安全性越高,串行化执行越严重,降低数据库的并发度。Oracle默认为READ-COMMITTED, MySQL默认为REPEATABLE-READ
事务并发访问引起的问题以及如何避免
1. 更新丢失—MySQL所有事务隔离级别再数据库层面上均可避免
一个事务的更新覆盖了另一个事务的更新,目前主流数据库都会主动加锁来避免更新丢失的情况。
2. 脏读—READ-COMMITTED事务隔离级别以上可避免
一个事务读取另一个事务未提交的更新数据
3. 不可重复读—REPEATABLE-READ事务隔离级别以上可避免
多次读取操作返回的结果不一致现象
4. 幻读—SERIALIZALE事务隔离级别可避免
事务A读取与搜索条件相匹配的若干行,事务B通过删除或插入改变了事务A的结果集
InnoDB可重复读隔离级别下如何避免幻读
表象:快照读(非阻塞读)—伪MVCC
当前读
加了锁的增删改查语句:select ... lock in share mode,select ... for update,update,delete,insert
快照读(隔离级别在SERIALIZALE一下才能成立)
不加锁的非阻塞读,select,提升并发执行的能力,开销低,读取数据可能不是最新版本
内在:next-key锁(行锁+gap锁)
对主键索引或者唯一索引会用Gap锁吗
- 如果where条件全部命中,则不会用Gap锁,只会加记录锁
- 如果where条件部分命中或者全不命中,则会加Gap锁
原文地址:https://www.cnblogs.com/sasworld/p/11517707.html