MySQL行级锁

行级锁是MySQL中粒度最小的一种锁,他能大大减少数据库操作的冲突。但是粒度越小,实现的成本也越高。MYISAM引擎只支持表级锁,而INNODB引擎能够支持行级锁,下面的内容也是针对INNODB行级锁展开的。
INNODB的行级锁有共享锁(S LOCK)和排他锁(X LOCK)两种。共享锁允许事物读一行记录,不允许任何线程对该行记录进行修改。排他锁允许当前事物删除或更新一行记录,其他线程不能操作该记录。

共享锁:
用法: SELECT … LOCK IN SHARE MODE;
MySQL会对查询结果集中每行都添加共享锁。
锁申请前提:当前没有线程对该结果集中的任何行使用排他锁,否则申请会阻塞。
操作限制:
使用共享锁线程与不使用共享锁线程对锁定记录操作限制表
线程 读取操作 写入操作 共享锁申请 排他锁申请
使用共享锁 可读 可写/不可写(报错) 可申请 可申请
不使用共享锁 可读 不可写(阻塞) 可申请 不可申请(阻塞)

  1. 使用共享锁线程可对其锁定记录进行读取,其他线程同样也可对锁定记录进行读取操作,并且这两个线程读取的数据都属于同一个版本。
  2. 对于写入操作,使用共享锁的线程需要分情况讨论,当只有当前线程对指定记录使用共享锁时,线程是可对该记录进行写入操作(包括更新与删除),这是由于在写入操作前,线程向该记录申请了排他锁,然后才进行写入操作;当其他线程也对该记录使用共享锁时,则不可进行写入操作,系统会有报错提示。不对锁定记录使用共享锁的线程,当然是不可进行写入操作了,写入操作会阻塞。
  3. 使用共享锁进程可再次对锁定记录申请共享锁,系统并不报错,但是操作本身并没有太大意义。其他线程同样也可以对锁定记录申请共享锁。
  4. 使用共享锁进程可对其锁定记录申请排他锁;而其他进程是不可以对锁定记录申请排他锁,申请会阻塞。

    排他锁:
    用法: SELECT … FOR UPDATE;
    MySQL会对查询结果集中每行都添加排他锁,在事物操作中,任何对记录的更新与删除操作会自动加上排他锁。
    锁申请前提:当前没有线程对该结果集中的任何行使用排他锁或共享锁,否则申请会阻塞。
    操作限制:
    使用排他锁线程与不使用排他锁线程对锁定记录操作限制表
    线程 读取操作 写入操作 共享锁申请 排他锁申请
    使用排他锁 可读(新版本) 可写 可申请 可申请
    不使用排他锁 可读(旧版本) 不可写(阻塞) 不可申请(阻塞) 不可申请(阻塞)

  5. 使用排他锁线程可以对其锁定记录进行读取,读取的内容为当前事物的最新版本;而对于不使用排他锁的线程,同样是可以进行读取操作,这种特性是一致性非锁定读。即对于同一条记录,数据库记录多个版本,在事物内的更新操作会反映到新版本中,而旧版本会提供给其他线程进行读取操作。

  6. 使用排他锁线程可对其锁定记录进行写入操作;对于不使用排他锁的线程,对锁定记录的写操作是不允许的,请求会阻塞。
  7. 使用排他锁进程可对其锁定记录申请共享锁,但是申请共享锁之后,线程并不会释放原先的排他锁,因此该记录对外表现出排他锁的性质;其他线程是不可对已锁定记录申请共享锁,请求会阻塞。
  8. 使用排他锁进程可对其锁定记录申请排他锁(实际上并没有任何意义);而其他进程是不可对锁定记录申请排他锁,申请会阻塞。

来源: http://blog.youkuaiyun.com/tigernorth/article/details/7948539

### MySQL 行级锁的工作原理 在MySQL中,行级锁主要用于InnoDB存储引擎。这种锁机制允许事务锁定单个记录而不是整个表,从而提高了并发处理能力[^1]。 当一个事务对某一行数据进行了修改操作(如`INSERT`, `UPDATE`, 或者 `DELETE`),该事务会自动获得这行数据上的排他锁(exclusive lock),阻止其他任何事务对该行进行读取或写入直到当前事务完成并释放此锁为止。对于只读查询(`SELECT ... FOR UPDATE`)也会请求相应的行级锁以防止被选中的行在此期间发生变化[^4]。 另外,在某些情况下即使没有显式指定,InnoDB也可能会隐含地施加行级别的锁。例如,如果执行了一个范围查找语句,则不仅会对找到的结果集里的每一行都上锁,还会对其索引区间两端附加额外的间隙锁(gap locks)来预防幻影读现象的发生[^5]。 #### 死锁及其解决方案 由于多线程环境下不同进程之间相互等待对方持有的资源而形成循环依赖关系即发生死锁的情况较为常见;因此理解如何有效管理这些锁变得至关重要: - **避免长时间持有锁**:尽量缩短事务持续的时间长度,减少不必要的大事务。 - **统一锁定顺序**:确保所有程序按照相同的顺序去获取相同对象上的锁可以大大降低出现死结的概率。 - **启用死锁超时与检测功能**:MySQL本身具备一套完善的死锁监测算法能够及时发现此类异常状况,并且回滚其中一个参与方以便打破僵局继续正常运作下去。 ### 应用场景分析 考虑到上述特性,下面列举了一些适合采用行级锁定策略的具体实例: - 当应用程序频繁更新特定几条记录而非整张表格的数据项时; - 对于高频率发生的短周期型业务逻辑而言,比如电商网站的商品库存调整过程就非常适合运用这种方式来进行保护以免产生竞争条件问题; - 数据仓库环境中针对历史事实表实施ETL作业过程中同样适用因为每次加载的新批次通常只会涉及新增的部分而非覆盖已有内容。 ```sql -- 示例SQL展示如何利用行级锁实现安全可靠的并发控制 BEGIN; SELECT * FROM orders WHERE order_id = 1024 FOR UPDATE; -- 加行级X锁, 防止其它session修改这条order记录 UPDATE orders SET status='shipped' WHERE order_id=1024; COMMIT; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值