无论何时,只要有多个查询需要在同一时刻修改数据,都会产生并发控制的问题,MySQL在解决并发问题的时候,是通过实现一个由两种类型的锁组成的锁系统来解决的:
读写锁
事务可以通过以下语句给sql加共享锁和排他锁:
共享锁:select …… lock in share mode;
排他锁:select …… for update;
1.共享锁(shared lock)
共享锁也叫读锁(read lock),是读取操作创建的锁。其他用户可以并发读取数据,但任何事务都不能对数据进行修改(获取数据上的排他锁),直到已释放所有共享锁。
如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁。获准共享锁的事务只能读数据,不能修改数据。
2.排他锁(exclusive lock)
排他锁也叫写锁(write lock),写锁是排他的,一个写锁会阻塞其他的写锁和读锁
读锁和写锁都是行级锁,InnoDB的行锁是通过给索引上的索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁,InnoDB行锁分为3中情形:
1. Record Lock:对索引项加锁。
2. Gap Lock:对索引项之间的“间隙”、第一条记录前的“间隙”或最后一条记录后的“间隙”加锁。
3. Next-key Lock:前两种的结合,对记录及其前面的间隙加锁。
InnoDB这种行锁的实现特点意味着,如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟锁表一样。
锁粒度
所谓的锁策略,就是在锁的开销和数据的安全性之间寻求平衡.MySQL的每种存储引擎都可以实现自己的锁策略和锁粒度,下面介绍最重要的两种锁策略.
表锁(table lock)
表锁是MySQL中最基本的锁策略,并且是开销最小的策略.它会锁定整张表,一个用户在对表进行写操作(插入,删除,更新等)前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作.只有没有写锁时,其他读取的用户才能获得读锁,读锁之间是不相互阻塞的.
写锁比读锁有更高的优先级,因此一个写锁请求可能会被插入到读锁队列的前面.
尽管存储引擎可以管理自己的锁,MySQL本身还是会使用各种有效的表锁来实现不同的目的.例如,服务器会为诸如ALTER TABLE之类的语句使用表锁,而忽略存储引擎的锁机制.
行级锁(row lock)
行级锁可以最大程度的支持并发处理(同时也带来了最大的锁开销).行级锁只有在存储引擎增实现,而MySQL服务器层没有实现.服务器层完全不了解存储引擎中的锁机制.