目录
1、Mysql锁机制
- 表级锁(锁定整个表)
- 页级锁(锁定一页)
- 行级锁(锁定一行)
- 共享锁(S锁,MyISAM 叫做读锁)
- 排他锁(X锁,MyISAM 叫做写锁)
- 悲观锁(抽象性,不真实存在这个锁)
- 乐观锁(抽象性,不真实存在这个锁)
乐观锁和悲观锁
乐观锁和悲观锁都是针对读(select)来说的。
1.乐观锁
乐观锁是指 在操作数据时非常乐观,认为别的线程不会同时修改数据,所以不会上锁,但是在更新的时候会判断一下在此期间别的线程有没有更新过这个数据。
- 乐观锁不是数据库自带的,需要我们自己去实现。
通常实现是这样的:在表中的数据进行更新时,先给数据表加一个版本(version)字段,每操作一次,将那条记录的版本号加1。
- 先查询出那条记录,获取出version字段。
- 如果要对那条记录进行更新操作,则先判断此刻version的值是否与刚刚查询出来时的version的值相等。
- 如果相等,则说明这段期间没有其他程序对其进行操作,则可以执行更新,将version字段的值加1。
- 如果version值与刚刚获取出来的version的值不相等,则说明这段期间已经有其他程序对其进行操作了,则不进行更新操作。
乐观锁更新有可能会失败,甚至是更新几次都失败,这是有风险的。所以如果写入居多,对吞吐要求不高,可使用悲观锁。
2.悲观锁
悲观锁在操作数据时比较悲观,每次去拿数据的时候认为别的线程也会同时修改数据,所以每次在拿数据的时候都会上锁,这样别的线程想拿这个数据就会阻塞直到它拿到锁。这点跟java中的synchronized很相似,所以悲观锁需要耗费较多的时间。
- 悲观锁是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了。
- 悲观锁涉及到的另外两个锁:就是共享锁与排它锁。
- 共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。
共享锁与排他锁
数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。
1.共享锁
- 共享锁(S):当事务对数据加上共享锁后,其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
- 加共享锁 (S) : select * from table_name where ... lock in share mode;
- 共享锁只能兼容共享锁,不兼容排它锁
2.排他锁
- 排他锁(X):如果事务T对数据A加上排他锁后,则其他事务不能再对数据A加任任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
- 加排他锁(x) : select* from table_name where ... for update;
- 排它锁互斥共享锁和其它排它锁
行锁与表锁
1.行锁
mysql锁机制分为表级锁和行级锁。mysql行级锁包括共享锁与排他锁:
- 共享锁又称为读锁,简称S锁
- 共享锁:多个事务都可以加共享锁读同⼀⾏数据,但是别的事务不能写这⾏数据。
- 一个事务获取了共享锁,其他事务也只能加共享锁或不加锁查询。
- 其他事务不能写。
- 其他事务加排他锁查不到,因为排他锁与共享锁不能存在同一数据上。
- 共享锁:多个事务都可以加共享锁读同⼀⾏数据,但是别的事务不能写这⾏数据。
- 排他锁又称为写锁,简称X锁
- 排他锁:⼀个事务可以读/写这⾏数据,别的事务只能读不能写。
- 一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。
- 获取排他锁的事务可以对数据就行读取和修改。
- 其他事务可以通过select ...from...查询数据,因为普通查询没有任何锁机制。
- 其他事务不能写。
- 排他锁:⼀个事务可以读/写这⾏数据,别的事务只能读不能写。
mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型。
1.表锁
innodb的 表锁,分成意向共享锁 和意向拍他锁,表锁是innodb引擎⾃动加的,不⽤你⾃⼰去加。
- 意向共享锁:加共享⾏锁时,必须先加共享表锁;
- 意向排他锁 :给某⾏加排他锁时,必须先给表加排他锁。
- insert、update、delete,innodb会⾃动给那⼀⾏加⾏级排他锁。
- select,innodb啥锁都不加。
mysql innodb 存储引擎的默认锁模式,其实还挺不错的。相当于就是⼀⾏数据,同⼀个时刻只能⼀个⼈在修改,但是别⼈修改,你可以随便读,读是读某个版本的,⾛mvcc 机制。