锁
悲观锁
概念
当多事务争取一个资源时,有可能导致数据不一致,这个时候需要一种机制限制,并且将数据访问顺序化,用来保证数据库数据的一致性,锁就是其中的一种机制。
锁类型
数据库上的操作可以归纳为两种:读和写。
多个事务同时读取一个对象的时候,是不会有冲突的。同时读和写,或者同时写才会产生冲突。因此为了提高数据库的并发性能,通常会定义两种锁:共享锁和排它锁。它们都实现了悲观锁的思想;
共享锁(Shared Lock,也叫S锁,读锁)
lock in share model
共享锁(S)表示对数据进行读操作。因此多个事务可以同时为一个对象加共享锁。
产生共享锁的sql:select * from ad_plan lock in share mode;
注意:上了共享锁之后,可以进行添加排他锁,但是容易产生死锁,Mysql能解决自身的锁机制,通过事务回滚
排它锁(X锁,写锁):for update
排他锁也叫写锁(X)。
排他锁表示对数据进行写操作。如果一个事务对对象加了排他锁,其他事务就不能再给它加共享锁或者排它锁了。
产生排他锁的sql: select * from ad_plan for update;看到了吧,for update出现了,所以for update 就是排他锁,
注意: insert,update,delete自带排它锁;
间隙锁:
排它锁进行返回锁的时候,对主键不存在的记录也上锁了
三级封锁协议
一级封锁协议:事务T中如果对数据R有写操作,必须在这个事务中对R的第一次读操作前对它加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。
二级封锁协议:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后方可释放S锁。
三级封锁协议:一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。
#悲观锁 - 思想
#mysql
# 共享锁、排他锁 - 属于行锁,只会锁行
# 共享锁、排他锁 - 悲观锁的具体实现
# 共享锁:lock in share mode, 一旦某个事务对一条(多条)记录添加共享锁之后,其他事务就无法再对该记录添加排他锁,但是可以继续添加共享锁
# 排他锁:for update, 一旦某个事务对一条(多条)记录添加排他锁之后,其他事务就无法再对该记录添加排他锁或者共享锁
# 排他锁和共享锁只能添加到select语句之后,insert、update、delete默认自带排他锁
# 如果一个事务对一条记录添加了排他锁,其他事务无法再执行insert、update、delete、select for update,但是可以单纯的select
# 排他锁必须基于主键或者一个唯一性索引,才能添加。如果条件中没有主键或者唯一性索引,则该排他锁会默认变成表锁
#id <= 77 行锁会锁住77以前的id, 77以后的id其他事务是可以操作的 ??? 为啥78会被锁
#77以前不存在的id,称为间隙锁