主要看在事务中不存在则插入的阻塞情况。
表定义:
mysql> desc user; +-------------+------------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+------------------+------+-----+-------------------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | name | varchar(50) | NO | MUL | NULL | | | password | char(20) | NO | | NULL | | | regist_time | timestamp | NO | | CURRENT_TIMESTAMP | | +-------------+------------------+------+-----+-------------------+----------------+ 4 rows in set (0.00 sec)
client1:
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from user; +----+------+----------+---------------------+ | id | name | password | regist_time | +----+------+----------+---------------------+ | 1 | a | a | 2018-03-11 16:32:43 | | 2 | b | b | 2018-03-11 16:33:09 | | 3 | c | c | 2018-03-11 16:33:39 | +----+------+----------+---------------------+ 3 rows in set (0.00 sec) mysql> insert into user(name,password) select ‘d‘,‘d‘ from dual where not exist (select name from user where name=‘d‘); Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0 mysql> select * from user; +----+------+----------+---------------------+ | id | name | password | regist_time | +----+------+----------+---------------------+ | 1 | a | a | 2018-03-11 16:32:43 | | 2 | b | b | 2018-03-11 16:33:09 | | 3 | c | c | 2018-03-11 16:33:39 | | 4 | d | d | 2018-03-11 17:03:35 | +----+------+----------+---------------------+ 4 rows in set (0.00 sec)
然后启动client2:
mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from user; +----+------+----------+---------------------+ | id | name | password | regist_time | +----+------+----------+---------------------+ | 1 | a | a | 2018-03-11 16:32:43 | | 2 | b | b | 2018-03-11 16:33:09 | | 3 | c | c | 2018-03-11 16:33:39 | +----+------+----------+---------------------+ 3 rows in set (0.00 sec) mysql> select * from user where name=‘d‘; Empty set (0.02 sec) mysql> insert into user (name,password) select ‘d‘,‘d‘ from dual where not exists (select name from user where name=‘d‘);
client2 执行“ insert into user (name,password) select ‘d‘,‘d‘ from dual where not exists (select name from user where name=‘d‘); ”出现阻塞,直到超时或client1 commit。
client2 直接执行插入操作则不会阻塞:
mysql> insert into user(name, password) values (‘d‘,‘d‘); Query OK, 1 row affected (0.00 sec)
client2 执行:
mysql> insert into user (name,password) select ‘e‘,‘e‘ from dual where not exists (select name from user where name=‘e‘);
也会出现阻塞,可见,这种情况使用的是表锁。另:如果已经存在name=‘d‘的数据,client1执行"insert not exists"后并不会使用表锁,client2执行时不会阻塞。
client1 查询后commit:
mysql> select * from user; +----+------+----------+---------------------+ | id | name | password | regist_time | +----+------+----------+---------------------+ | 1 | a | a | 2018-03-11 16:32:43 | | 2 | b | b | 2018-03-11 16:33:09 | | 3 | c | c | 2018-03-11 16:33:39 | | 4 | d | d | 2018-03-11 17:03:35 | +----+------+----------+---------------------+ 4 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.04 sec)
client2 查询后commit:
mysql> select * from user; +----+------+----------+---------------------+ | id | name | password | regist_time | +----+------+----------+---------------------+ | 1 | a | a | 2018-03-11 16:32:43 | | 2 | b | b | 2018-03-11 16:33:09 | | 3 | c | c | 2018-03-11 16:33:39 | | 5 | d | d | 2018-03-11 17:36:16 | +----+------+----------+---------------------+ 4 rows in set (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.04 sec)
注意client1 和 client2 name=‘d‘的id。
另:on duplicate key只适用于unique key,如果不是unique,总是会插入
mysql> insert into user(name,password) values(‘d‘,‘d‘) on duplicate key update password=‘e‘;
这时会插入一条name=‘d‘,password=‘d‘的记录。