Mysql 数据库锁机制

前言

需要了解下Mysql 锁机制相关的知识. 发现两篇不错的文章, 但是文章内有不少错误. 更正总结如下:


章节要点

  • 锁: 共享锁 / 排他锁 / 更新锁 / 意向锁 - (读锁/写锁)
  • 概念锁: 悲观锁 / 乐观锁
  • 范围: 行级锁 / 表级锁 / 页级锁

感觉我们经常接触的就是这些. 看了文章后, 豁然开朗. 这边将错误更新后分享给大家.


正文

一、锁

我们经常遇到的Mysql数据库内的锁主要分为: 共享锁 / 排他锁 / 更新锁 / 意向锁. 其中, 共享锁 / 排他锁有时因为其类型, 也被人们称为读锁/写锁.

  • 共享锁
    可以通过select xxx lock in share mode的方式, 添加共享锁.
# 线程1
select * from A where id = 1  in share mode; (添加共享锁)
# 线程2
select * from A where id = 2  in share mode; (添加共享锁)

线程1和线程2可以同时运行.

共享锁通常是多个线程读取同一份文件时后时候. 为了是将其写操作时的, 排他锁(写锁)进行区分.

  • 排他锁
    Mysql内通过select xx for update添加排他锁. 此外, 当进行insert/update/delete操作时会自动添加排他锁(?).
# 线程1
select * from A where id = 1 for update
# 线程2
select * from A where id = 1 for update

线程1和线程2互斥.

  • 更新锁
    更新锁是SQL SERVER内的概念. Mysql内无此概念.

  • 意向锁
    意向锁是数据库自己加的. 意向锁的作用在于, 判断是否表内是否存在锁.
    比如在更新操作时, 有两个线程: 线程A和线程B. 线程A锁定一行数据, 添加了行级排他意向锁; 线程B此时需要添加表级意向排他锁, 此时, 如果没有排他锁的话. 线程B需要对表进行扫描, 判断是否有锁的存在. 这样消耗大量的时间.


锁: 概念划分

锁从概念上划分可以分为: 乐观锁悲观锁. 其中, 乐观锁Mysql内需要自己进行实验.

  • 乐观锁
    乐观锁, 物如其名, 非常乐观. 乐观锁, 认为, 自己在并发的情况下, 不会出现线程相互影响的情况. 在事务进行提交前, 乐观锁需要校验下数据, 如果出现数据错误, 则进行回滚.

乐观锁认为, 在并发情况下, 其他事务不会操作自己正在操作的数据, 也就是不会加锁. 并发度高, 安全性低.

比如:

# 线程2
update a set name="1" where id =1
# 线程1
select * from a

当两个线程同时运行. 乐观锁认为, 线程1先执行完成, 线程2后于线程1进行更新数据. 当然, 当线程2先线程1执行的时候, 线程1是需要进行回滚的.

乐观锁通常使用一个版本号进行并发控制.

T1: 
select * from A;
update A set a=1,version=version+1 where id=1 and version=vs;
T2:
select * from A;
update A set a=2,version=version+1 where id=1 and version=vs;
-- vs为事务取得的版本号
  • 悲观锁
    悲观锁. 悲观锁在操作数据时, 通常会给数据加锁, 防止其他事务进行操作. 悲观锁通常使用于竞争激烈的情况. 并发度低, 安全性高.
BEGIN;
SELECT * FROM goods WHERE id=1 FOR UPDATE;
UPDATE goods SET stock=stock-1 WHERE id = 1;
COMMIT;

锁: 范围划分

锁, 从范围划分, 可以分为行级锁, 表级锁. Mysql内还有一个页级别锁的概念.

通常来时, InnoDB默认使用行级锁, MyIsAM默认使用表级别锁. 当然, 根据搜索的列是否有索引, 有时InnoDB也会添加表级别锁.

(id 上有索引, 则是行级别锁)
select id from A where id =1 lock in share mode ;
(name 上无索引, 则是表级别锁)
select name from A where name =1 lock in share mode ;

Others

Mysql 执行select查询语句的时候 会自动加锁吗?
[]InnoDB会根据事务隔离级别自动加锁,当然程序员可以手动加锁,但通常手动加锁不但没有必要还会影响性能;InnoDB的行级锁已经经过许多优化了。 ----来自高性能MySQL

附議第三個回答,解鎖方式取決於事務的隔離等級。

『浅入浅出』MySQL 和 InnoDB


Reference

[1]. MySQL锁详解
[2]. 数据库锁机制及乐观锁,悲观锁的并发控制
[3]. 详解mysql的for update
[4]. MySQL 排它锁 详解

至于更多的详细理解, 个人觉得应当看下书高性能Mysql. 网上的说法五花八门的. 后续的补充和更改, 等我看完书后回来更.

各位看个概念, 具体细节. 没有特别适合的好博文.


不推荐引用

写的五花八门.
mysql的表锁和行锁,排他锁和共享锁。
Mysql(行锁,表锁,共享锁,排他锁,乐观锁,悲观锁)
mysql共享锁与排他锁
数据库锁分类和总结
数据库锁总结

展开阅读全文

没有更多推荐了,返回首页