乐观锁、悲观锁
https://blog.csdn.net/u013521882/article/details/85275987
mysql锁机制分为 表锁、行锁。
- 表锁:
- 行锁:共享锁、排它锁
mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁
select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句
排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。
对于共享锁大家可能很好理解,就是多个事务只能读数据不能改数据,对于排他锁大家的理解可能就有些差别,我当初就犯了一个错误,以为排他锁锁住一行数据后,其他事务就不能读取和修改该行数据,其实不是这样的。排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁。mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。
意向锁
在 InnoDB 引擎中,是允许行锁和表锁共存的。但是这样就会有一个问题,假如事务 A 给 t 表其中一行数据上锁了,这时候事务 B 想给 t 表上一个表锁,这时候怎么办呢?事务 B 怎么知道 t 表有没有行锁的存在,如果采用全表遍历的情况,当表中的数据很大的话,加锁都要加半天,效率直线下降,所以为了避免这个问题, MySQL 中就又引入了意向锁。
意向锁也是属于表锁的一种,分为两种类型:意向共享锁(Intention Shared Lock)和意向排他锁(Intention Exclusive Lock),这两种锁又分别可以简称为 IS 锁和 IX 锁。
意向锁是 MySQL 自己维护的,用户无法手动加意向,意向锁有两大加锁规则:
当需要给一行数据加上 S 锁的时候,MySQL 会先给这张表加上 IS 锁。
当需要给一行数据加上 X 锁的时候,MySQL 会先给这张表加上 IX 锁。
这样的话上面的问题就迎刃而解了,当需要给一张表上表锁的时候,只需要看这张表是否有对应的意向锁就可以了,无需遍历整张表。
间隙锁
间隙锁 是Innodb在 (可重复读隔离级别)的情况下为了解决幻读才引入的机制。
幻读的问题存在是因为新增或者更新操作,这时如果进行范围查询的时候(加锁查询),会出现不一致的问题,这时使用不同的行锁已经没有办法满足要求,需要对一定范围内的数据进行加锁,间隙锁就是解决这类问题的。在可重复读隔离级别下,数据库是通过行锁和间隙锁共同组成的(next-key lock),来实现的
间隙锁查看
死锁是互斥的,间隙锁不是互斥的,插入要小心。
表锁
行锁与表锁是基于索引来说的(且索引要生效)
窗口1
##设置不自动提交
## title不是索引的时候,会变成表锁。
## 如果不想产生表锁,需要给name添加索引。
set autocommit = 0;
update goods set status=1 where title='abc';
新开窗口
update goods set status=2 where title='ddd';
##结果 阻塞中...
##新开窗口
insert into goods(status,title) values(1, "cccc");
##结果 阻塞中...
MySQL事务隔离级别
事物隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | 是 | 是 | 是 |
不可重复读 | 否 | 是 | 是 |
可重复读 | 否 | 否 | 是 |
串行化 | 否 | 否 | 否 |
- 1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
- 2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
- 3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
MVCC并发版本控制
- 当前读
像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。
- 快照读
像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是串行级别,串行级别下的快照读会退化成当前读;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本
- 当前读,快照读和MVCC的关系
准确的说,MVCC多版本并发控制指的是 “维持一个数据的多个版本,使得读写操作没有冲突” 这么一个概念。仅仅是一个理想概念
而在MySQL中,实现这么一个MVCC理想概念,我们就需要MySQL提供具体的功能去实现它,而快照读就是MySQL为我们实现MVCC理想模型的其中一个具体非阻塞读功能。而相对而言,当前读就是悲观锁的具体功能实现.要说的再细致一些,快照读本身也是一个抽象概念,再深入研究。MVCC模型在MySQL中的具体实现则是由 3个隐式字段,undo日志 ,Read View 等去完成的,具体可以看下面的MVCC实现原理
https://blog.csdn.net/u010002184/article/details/88526708
redo undo binlog