mysql select lock_【MySQL】select for update 的Row Lock 与Table Lock

select for update 对表施加的锁模式分两种情况:

只有当where 条件中明确地使用指定主键时,MySQL 才会对表执行Row lock (只锁住被选取的数据) ,

否则MySQL 将会执行Table Lock (将整个数据表单给锁住)。

下面以具体的实例验证上面的结论:

注意 表mail_queue 的结构如下

root@127.0.0.1 : test 22:06:52> show create table mail_queue \G

*************************** 1. row ***************************

Table: mail_queue

Create Table: CREATE TABLE `mail_queue` (

`mail_id` int(11) NOT NULL AUTO_INCREMENT,

`is_sent` tinyint(4) NOT NULL COMMENT '是否已经发送(-1,失败,0没发送,1发送成功)',

`mail_title` varchar(127) NOT NULL COMMENT '邮件标题',

`mail_from` varchar(127) NOT NULL COMMENT '邮件发件人',

`mail_to` varchar(127) NOT NULL COMMENT '邮件接收人',

`mail_content` text NOT NULL COMMENT '邮件内容',

`add_time` int(11) NOT NULL COMMENT '?'

`send_time` int(11) NOT NULL COMMENT '?'

`agent_id` int(11) NOT NULL COMMENT '?',

`service_id` int(11) NOT NULL COMMENT 'ID',

PRIMARY KEY (`mail_id`),

KEY `ind_mq_atime_isent_mail_id` (`add_time`,`is_sent`,`mail_id`),

KEY `sid` (`service_id`)

) ENGINE=InnoDB AUTO_INCREMENT=7391601 DEFAULT CHARSET=utf8 COMMENT='邮件队列'

1 row in set (0.00 sec)

例1: (明确指定主键,并且有此数据,row lock)

session1

root@127.0.0.1 : test 21:50:40> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

root@127.0.0.1 : test 21:50:56>

root@127.0.0.1 : test 21:50:56> select mail_id from mail_queue where mail_id=237 for update;

+---------+

| mail_id |

+---------+

|     237 |

+---------+

1 row in set (0.00 sec)

session2

root@127.0.0.1 : test 21:51:42> set autocommit=0;

Query OK, 0 rows affected (0.00 sec)

root@127.0.0.1 : test 21:51:48> select mail_id from mail_queue where mail_id=237;

+---------+

| mail_id |

+---------+

|     237 |

+---------+

1 row in set (0.00 sec)

例2: (明确指定主键,若查无此数据,无lock)

session 1

root@127.0.0.1 : test 22:06:05> select mail_id from mail_queue where mail_id=-1 for update;

Empty set (0.00 sec)

session 2

root@127.0.0.1 : test 22:06:45> select mail_id,is_sent from mail_queue where mail_id=237 for update;

+---------+---------+

| mail_id | is_sent |

+---------+---------+

|     237 |       1 |

+---------+---------+

1 row in set (0.00 sec)

例3: (无主键,table lock)

mail_to 非主键

session 1

root@127.0.0.1 : test 22:09:20> select mail_to from mail_queue where mail_to='slxx_721521@126.com' for update;

+---------------------+

| mail_to             |

+---------------------+

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

| slxx_721521@126.com |

+---------------------+

10 rows in set (50.23 sec)

session 2 查询被阻塞

root@127.0.0.1 : test 22:10:02> select mail_id,is_sent from mail_queue where mail_id=237 for update;

Ctrl-C -- sending "KILL QUERY 38535" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution was interrupted

root@127.0.0.1 : test 22:11:30>

例4: (主键不明确,table lock)

session 1

root@127.0.0.1 : test 22:11:48> select count(1) from mail_queue where mail_id <> 100000 for update;

+----------+

| count(1) |

+----------+

|  3695458 |

+----------+

1 row in set (27.45 sec)

session 2 会话被锁

root@127.0.0.1 : test 22:12:35> select mail_id,is_sent from mail_queue where mail_id=237 for update;

Ctrl-C -- sending "KILL QUERY 38535" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution was interrupted

root@127.0.0.1 : test 22:13:10>

例5: (主键不明确,table lock)

session 1

root@127.0.0.1 : test 22:13:46> select count(1) from mail_queue where mail_id like '100000' for update;

+----------+

| count(1) |

+----------+

|        0 |

+----------+

1 row in set (24.31 sec)

root@127.0.0.1 : test 22:14:22>

session 2

root@127.0.0.1 : test 22:13:34> select mail_id,is_sent from mail_queue where mail_id=237 for update;

Ctrl-C -- sending "KILL QUERY 38535" to server ...

Ctrl-C -- query aborted.

ERROR 1317 (70100): Query execution was interrupted

注:FOR UPDATE 仅适用于InnoDB,且必须在事务区块(BEGIN/COMMIT)中才能生效。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值