Mysql 数据库锁机制 Dear 丶 2022-02-09 14:11 141阅读 0赞 ### 前言 ### 需要了解下`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查询语句的时候 会自动加锁吗?][Mysql _select_] > \[\]InnoDB会根据事务隔离级别自动加锁,当然程序员可以手动加锁,但通常手动加锁不但没有必要还会影响性能;InnoDB的行级锁已经经过许多优化了。 ----来自高性能MySQL > > 附議第三個回答,解鎖方式取決於事務的隔離等級。 > [『浅入浅出』MySQL 和 InnoDB][MySQL _ InnoDB] -------------------- ### Reference ### \[1\]. [MySQL锁详解][MySQL] \[2\]. [数据库锁机制及乐观锁,悲观锁的并发控制][Link 1] \[3\]. [详解mysql的for update][mysql_for update] \[4\]. [MySQL 排它锁 详解][MySQL _] 至于更多的详细理解, 个人觉得应当看下书`高性能Mysql`. 网上的说法五花八门的. 后续的补充和更改, 等我看完书后回来更. 各位看个概念, 具体细节. 没有特别适合的好博文. -------------------- ### 不推荐引用 ### 写的五花八门. [mysql的表锁和行锁,排他锁和共享锁。][mysql] [Mysql(行锁,表锁,共享锁,排他锁,乐观锁,悲观锁)][Mysql] [mysql共享锁与排他锁][mysql 1] [数据库锁分类和总结][Link 2] [数据库锁总结][Link 3] [Mysql _select_]: https://segmentfault.com/q/1010000010645683 [MySQL _ InnoDB]: https://draveness.me/mysql-innodb.html [MySQL]: https://www.cnblogs.com/luyucheng/p/6297752.html [Link 1]: https://www.cnblogs.com/ouhaitao/p/8039537.html [mysql_for update]: https://blog.csdn.net/u011957758/article/details/75212222 [MySQL _]: https://blog.csdn.net/chenshun123/article/details/79661680 [mysql]: https://www.cnblogs.com/shamgod-lct/p/9318032.html [Mysql]: https://blog.csdn.net/qiwansong/article/details/81874256 [mysql 1]: https://www.cnblogs.com/boblogsbo/p/5602122.html [Link 2]: https://blog.csdn.net/weixin_39651041/article/details/79985715 [Link 3]: https://www.cnblogs.com/ismallboy/p/5574006.html
还没有评论,来说两句吧...