MySQL replace into 造成死锁
错误日志如下:
1.replace into 的作用是,当存在冲突时,会把旧的记录替换成新的记录,也就是说replace into 分了两个步骤:A.判断 和 B. 执行
A. 首先判断我们执行的记录是否存在(根据主键或者唯一索引)
B. 针对不存在的记录,直接执行insert语句
针对已经存在的记录,语句拆分为:delete + insert 执行
2.测试如下:
mysql> show tables; +----------------+ | Tables_in_yoon | +----------------+ | hank | +----------------+ 1 row in set (0.00 sec) mysql> select * from hank; +----+------+ | id | name | +----+------+ | 1 | yoon | | 2 | hank | | 3 | yoon | | 4 | aaa | +----+------+ 4 rows in set (0.00 sec) mysql> replace into hank (id,name) values (5,'CCC'); Query OK, 1 row affected (0.00 sec) mysql> replace into hank (id,name) values (4,'KKK'); Query OK, 2 rows affected (0.00 sec)
3.死锁分析:
在多线程高并发的情况下,存在两个事务同时去获取一个记录的修改的情况:
A. 事务1拿到X记录锁
B. 事务2检测到冲突,获取X|NK锁,被事务1阻塞
C. 事务1检测到冲突,申请获取S|NK,被事务2阻塞
4.解决方法:(最好还是通过业务逻辑去优化)
使用 INSERT + ON DUPLICATE KEY UPDATE语句替换高并发环境下的Replace Into语句解决死锁问题
ON DUPLICATE KEY UPDATE语句的作用是:
A. 若该数据的主键值/ UNIQUE KEY 已经在表中存在,则执行更新操作, 即UPDATE 后面的操作
B. 否则插入一条新的记录