Mysql乐观锁与悲观锁

1.乐观锁

  • 在更新数据前认为不会有人同时修改该数据,在更新时再去校验数据是否被修改过
  • 实现方式: 通过给表字段增加version或者updated_at,每次更新数据后给version+1或者修改updated_at为当前时间, 在更新前去校验当前version值或updated_at是否与数据库中的最新值一致
session1:
MariaDB [blog]> select * from articles;
+----+-------+---------+---------------------+---------------------+
| id | title | content | created_at          | updated_at          |
+----+-------+---------+---------------------+---------------------+
|  2 | zz    | zzz     | 0000-00-00 00:00:00 | 2018-05-06 16:59:03 |
|  9 | as    | NULL    | 0000-00-00 00:00:00 | 0000-00-00 00:00:00 |
+----+-------+---------+---------------------+---------------------+
2 rows in set (0.00 sec)

-----------------------------------------------------------------------------

session2:
MariaDB [blog]> update articles set title = "cc", updated_at = NOW() where id = 2;
Query OK, 1 row affected (17.17 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-----------------------------------------------------------------------------

session1:
MariaDB [blog]> update articles set title = "xx" where id = 2 and updated_at = "2018-05-06 16:59:03";
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0

2. 悲观锁

  • 分为共享锁和排它锁
  • 共享锁:也叫读锁,简称S锁,原理:一个事务获取了一个数据行的共享锁,其他事务能获得该行对应的共享锁,但不能获得排他锁,即一个事务在读取一个数据行的时候,其他事务也可以读,但不能对该数据行进行删除和更新。
 session1:
MariaDB [blog]> begin;
Query OK, 0 rows affected (0.00 sec)

MariaDB [blog]> select * from articles where id = 2 lock in share mode;
+----+-------+---------+---------------------+---------------------+
| id | title | content | created_at          | updated_at          |
+----+-------+---------+---------------------+---------------------+
|  2 | cc    | zzz     | 0000-00-00 00:00:00 | 2018-05-06 17:00:28 |
+----+-------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

-----------------------------------------------------------------------------

session2:
MariaDB [blog]> select * from articles where id = 2;
+----+-------+---------+---------------------+---------------------+
| id | title | content | created_at          | updated_at          |
+----+-------+---------+---------------------+---------------------+
|  2 | cc    | zzz     | 0000-00-00 00:00:00 | 2018-05-06 17:00:28 |
+----+-------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

MariaDB [blog]> update articles set title = "zz" where id = 2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [blog]> insert into articles(title) values("ss");
Query OK, 1 row affected, 2 warnings (0.00 sec)

MariaDB [blog]> delete from articles where id = 2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
  • 排它锁:也叫写锁,简称x锁,原理:一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的任何锁(排他锁或者共享锁),即一个事务在读取一个数据行的时候,其他事务不能对该数据行进行删除修改和加锁查询。对于update,insert,delete语句会自动加排它锁。
session1: 
MariaDB [blog]> begin;
Query OK, 0 rows affected (0.00 sec)

MariaDB [blog]> select * from articles where id = 2 for update;
+----+-------+---------+---------------------+---------------------+
| id | title | content | created_at          | updated_at          |
+----+-------+---------+---------------------+---------------------+
|  2 | cc    | zzz     | 0000-00-00 00:00:00 | 2018-05-06 17:00:28 |
+----+-------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

-----------------------------------------------------------------------------

session2:
MariaDB [blog]> begin;
Query OK, 0 rows affected (0.00 sec)

MariaDB [blog]> select * from articles where id = 2;
+----+-------+---------+---------------------+---------------------+
| id | title | content | created_at          | updated_at          |
+----+-------+---------+---------------------+---------------------+
|  2 | cc    | zzz     | 0000-00-00 00:00:00 | 2018-05-06 17:00:28 |
+----+-------+---------+---------------------+---------------------+
1 row in set (0.00 sec)

MariaDB [blog]> select * from articles where id = 2 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [blog]> delete from articles where id = 2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
MariaDB [blog]> select * from articles where id = 2 lock in share mode;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    原文作者:尘世那么美丽
    原文地址: https://www.jianshu.com/p/c74ca9b8718f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞