前言
在数据库中设计锁的目的是为了处理并发问题,在并发对资源进行访问时,数据库要合理控制对资源的访问规则。
而锁就是用来实现这些访问规则的一个数据结构。
在对数据并发操作时,没有锁可能会引起数据的不一致,导致更新丢失。
锁的分类
乐观锁和悲观锁
乐观锁: 对于出现更新丢失的可能性比较乐观,先认为不会出现更新丢失,在最后更新数据时进行比较。
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`value` int(11) DEFAULT NULL,
`version` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB ;
insert into t values(1,1,1);
select id,value,version from t where id=1;
update t set value=2,version=version+1 where id=1 and version=1;
复制代码
**悲观锁: ** 对于出现更新丢失的可能性比较悲观,在查询时就加锁,保证不被其他事务操作;可通过select...fot update实现。
select * from t where id = 1 for update;
复制代码
共享锁(S锁)和排他锁(X锁)
共享锁(shared lock)是指多个事务之间可以共享锁资源,一般都是在读取数据时添加,也称为读锁(read lock)。
select * from t where id = 1 lock in share mode;
复制代码
排它锁( exclusive lock,X锁),也称为写锁(write lock)。
当事务A对数据添加上X锁后,其他事务则不能再对该数据添加任何锁,直到事务A释放数据上的X锁。
增、删、改都会对数据添加X锁,在查询语句中使用for update也会添加X锁。
S锁 | X锁 | |
---|---|---|
S锁 | √ | × |
X锁 | × | × |
按加锁粒度区分
全局锁
顾名思义,全局锁是对整个数据库加锁,加锁之后整个库对其他事务都不能进行写操作。MySQL中提供一种添加全局读锁的方式,命令是:flush tables with read lock
(FTWRL)。
-- 加全局读锁
flush tables with read lock;
-- 解锁
unlock tables;
复制代码
使用场景:全库逻辑备份。
但是使用全局锁进行备份有以下问