相关连接:
for update 既可以锁表又可以锁行,具体怎么做的.直接从网上拿来一个版本:
利用select * for update 可以锁表/锁行。自然锁表的压力远大于锁行。所以我们采用锁行。什么时候锁表呢?
假设有个表单products ,里面有id跟name二个栏位,id是主键。
例1: (明确指定主键,并且有此笔资料,row lock)
SELECT * FROM wallet WHERE id=’3′ FOR UPDATE;
例2: (明确指定主键,若查无此笔资料,无lock)
SELECT * FROM wallet WHERE id=’-1′ FOR UPDATE;
例2: (无主键,table lock)
SELECT * FROM wallet WHERE name=’Mouse’ FOR UPDATE;
例3: (主键不明确,table lock)
SELECT * FROM wallet WHERE id<>’3′ FOR UPDATE;
例4: (主键不明确,table lock)
SELECT * FROM wallet WHERE id LIKE ‘3’ FOR UPDATE;
但是使用for update的时候需要注意以下几点:
一.for update开启的并非完全是排他锁X.如果有其他事务开启着共享锁S,那么for update根本不会阻塞.如下
#--------------------------事务1----------------------------
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select name from user where id =2;
+------+
| name |
+------+
| 22 |
+------+
1 row in set (0.00 sec)
#------------------------事务2----------------------
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select pl from user where id =2 for update;
+------+
| pl |
+------+
| 143 |
+------+
1 row in set (0.00 sec)
二.但是如果其他事务开启的是排他锁X.那么for update开启的也是排他锁X,可以看到下面的代码里,for update被阻塞了,直到排他锁X提交释放.
------------------------------
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set pl =123 where id =2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
------------------------------
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select pl from user where id =2 for update;
三.同样的,如果for update 未提交,那么其他排它锁X也是不能进来的.
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select pl from user where id =2 for update;
+------+
| pl |
+------+
| 123 |
+------+
1 row in set (10.70 sec)
-----------------这个很明显阻塞超时了-----------------------
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update user set pl =123 where id =2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
四.还有个问题,在第二种情况,如果for update 不在事务中,仍然生效.这个要注意.会比较坑.为了好管理,请全部在事务中.