多个事务同时更新一行数据,都会加锁,然后排队等待。一个事务执行并提交后,必须释放锁才能唤醒下一个事务继续执行。这多个事务在运行的时候加了哪些锁呢?它是一个X锁,一个Exclude独占锁。当一个事务加了排他锁,此时其他事务要更新这一行数据,就必须加一个排他锁,但只是临时获取一个排他锁,等以后再用。当有人在更新数据时,其他事务能否读取到这一行数据?你需要锁吗?不会,因为默认情况下,当有人在更新数据,然后你要读取它时,默认是打开MVCC的。即此时读写一行数据这两个操作默认不会加锁互斥,因为MySQL的MVCC就是为此设计的,避免了频繁的加锁互斥。这时候你读取数据的时候,就可以根据你的ReadView去undolog版本链上找一个你可以读取的版本,不用担心别人有没有更新。就算真的等它更新提交,基于MVCC,你也读取不到它的更新值!因为ReadView机制是不允许的,所以默认读取是完全不加锁的,不需要关心其他事务的更新和加锁问题,直接基于MVCC读取一个snapshot即可。如果要在执行查询操作时加锁怎么办?也能让你满意。MySQL支持共享锁和S锁。语法如下:select*fromtablelockinsharemode和addlockinsharemode在查询语句后,表示在查询时对一行数据加共享锁。如果此时其他事务正在更新这一行数据,加了排它锁,这时候还能加共享锁吗?如果你先加共享锁,然后其他人更新行,是否需要加排他锁?当然不行,这时候锁是互斥的,他只能等待。如果你加共享锁的时候其他人也加了共享锁怎么办?是的,你们两个都可以加共享锁,共享锁和共享锁是不互斥的。所以在更新数据的时候,必须加排它锁。独占锁和独占锁是互斥的,此时其他人无法更新;但是此时如果要查询,默认是不加锁的,使用MVCC读取快照版本,但是可以在查询的时候手动加共享锁,共享锁和排它锁是互斥的,共享锁和共享锁并不相互排斥。一般在开发业务系统的时候,很少有你在查询的时候主动加共享锁的。数据库行锁虽然实用,但一般不会在数据库层面进行复杂的手动加锁。而是使用基于redis/zookeeper的分布式锁。控制业务系统的锁逻辑。查询操作也可以加互斥锁:select*fromtableforupdate。我知道后会更新数据。这时候我加了排他锁。其他闲人等,请勿更新此数据!一旦你查询,加一个独占锁Lock,在你的事务提交之前,没有人可以更新数据。只有您可以更新此事务中的数据。提交后,其他人可以更新数据。总结本文介绍更新数据默认使用排他锁,查询数据的mvcc机制默认读取快照,然后通过查询加共享锁和排他锁,共享锁和排他锁之间的互斥规则。
