程序并发update同一张表或者并发insert 一张表

本文介绍如何通过优化表结构和索引解决MySQL并发操作导致的死锁问题,包括添加自增长主键和创建组合索引的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用索引解决MySQL死锁问题
摘要
MYSQL死锁解决过程
开启mysql死锁监控
查死锁信息
问题描述
问题解决方案
结论
摘要
当程序并发update同一张表,或者并发insert 一张表的时候都会出现数据库死锁问题。当并发insert一张表可能会出现间隙锁(小概率事件),这里先不谈,我主要描述update的常见的一种场景。

MYSQL死锁解决过程
开启mysql死锁监控
create table InnoDB_monitor(a INT) engine=InnoDB;
linux 环境重启myql

查死锁信息
查看死锁日志
在linux系统中:
先用 root 账号登录 mysql -uroot -proot。
然后用命令查看死锁信息 show engine innodb status \G;

在日志中找 LATEST DETECTED DEADLOCK 字样的日志,就是死锁日志。下面是我整理并截取的部分日志

问题描述
可以看到出现死锁的两条SQL分别是:
UPDATE BAL_REL SET USE_TOTAL=IFNULL(TOTAL_NUM,0)+‘4293’ WHERE BALANCE_ID=3420655500398712 AND USER_ID = 3072141520643085 AND SERV_ID=13510100 and USE_TOTAL < IFNULL(TOTAL_NUM,0)+‘4293’

UPDATE BAL_REL SET USE_TOTAL=IFNULL(TOTAL_NUM,0)+‘33442’ WHERE BALANCE_ID=3420655500398712 AND USER_ID = 3072141540643857 AND SERV_ID=13510100 and USE_TOTAL < IFNULL(TOTAL_NUM,0)+‘33442’

看下表模型设计:
由于表数据量比较大,加了三个索引,而且都是BTREE索引。

这样对更新同一个BALANCE_ID的update SQL 就有问题。由于BTREE存在,update 会锁住 BALANCE_ID索引节点下 每一条记录,就不是行级锁了。
https://blog.csdn.net/sturgsslecofwe/article/details/97938152
https://blog.csdn.net/sturgsslecofwe/article/details/97938462
https://blog.csdn.net/sturgsslecofwe/article/details/97938714

问题解决方案
(1)优化表结构
添加自增长的主键:
通过主键ID ,update每条数据,这时候使用的都是行锁。
设置手动提交事务 分别执行SQL,set autocommit=0; 并发执行两个SQL没有出现死锁。
https://www.qichamao.com/person/caa97deee42266f22643608681a394aa0db980a883c82b12ccacdab6ab20c3ca-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/243be674fb02d0815d1391628248bfe33c61e36924c0b04073b510a670199618-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/e49c2c4420212881731cfb1cb221ce6f9b241cd8ebb6226acb44e534f61974d9-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/c93e3196d74bf7b88dc39e2f4a500d6386de255cca113aa890774b3f49f795a2-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/2a0c42ff75ea7ad7d5a3610b13eaba4abd7c5e55a5e866407aa35ef8b6a6a68a-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/288a3c61f60aed3ba474a68131018bafa3375252ab9fd5de7c5e67276d493279-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/ca3985ef5bdf291d3a3e1132258476bca9de6573e6f1e1730e3d33445d44a418-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/a218d09b302ec463c75e54e9b74bbcc38882ebffe8a5913b348300e2c1d2f260a396766062fd556e8588ffae4bab3330-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/02c4b0a35379d1c6b0fb0cd3c3afcbba80cced413ff16851100f9e5af36aa491-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/e27c625cc4a90ef810e79c65ff29b38ded78f3076bc62f3f0e3bd5de131be77f-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/a6e580f6a12a79148df8043a94715be41e534714371606be88541f485ebe3e02-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/a17e4e3f36f9d5a9f1c82fb25c4b979367eaa0a25f4f3ac8466b5005f4ba01034ffaad6c1bd9bb7662489aa651d9011e-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/cea3baf7d3b697e4a42538440b7bff6b2614d62674c627bd0c1680d8dde12c8a-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/803b616c50170d67bc663130b4d66dd631767c0071f7239c05366d617e71145e-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/5fe0aa88e070fa282004b1d35925abf90648f68d0eb6169f8b22217a0c13f8075bfca1f02bc18e52d82bdfc7fafa480b-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/07786ecb72d31ba86ac979088355728e79791f8ec56034a665a5190243d5344f-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/d5be86a45e623dc038e44b761ead0864940739d063ce513bde4eb6e2c7afd3f9-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/0310d770565ee016b9afe452d1bbc48d198de31a68b5c80eb2e367328158fe791db1641776cf5e7b7e9a3206e55cd64b-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/ef1cc1cceef4fcd577c8b2784bc574f19824a1a12340deb25d41babd579cab40-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/ad441eaf72ba2048bfa4313f52e164a904045d0c66cba2dcf2e6f474883bf3c5-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/57b6120a214557e740d110ebb0414c2915487bdad30a90c63745cc3bfc34a7cc-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/42adc2a7d81792e60d6a7c80eed2a38e4e38af27def412d01b82902099eeae93-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/2ae8308db36b70ef7d1b387328da80d6a100f3ed805fc9295f73c8a10aa72910245e38d667688892add8d9e97f019796-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/4dbdf59f46928380f33cacb9622eb28445b1fe467e858626b3cec0922c710bd536bc11ba9b5b75d5dde9d665b177acad-2a6e52ffdd387b1510b9e27362ee9011
https://www.qichamao.com/person/ca843016999b4c1b133ba9fb46368bacbd7081bd6e38244cea1f49f7a313457f-2a6e52ffdd387b1510b9e27362ee9011

但是这样效率比较低,需要先查询到主键,然后update

(2)优化索引
可以看到SQL中where条件用了三个字段:BALANCE_ID,USER_ID,POOL_ID
添加一个组合索引 BALANCE_ID,USER_ID,POOL_ID

执行下SQL,没有出现锁等待,说明这种方式也是可以行,也不需要查询主键ID,相对来说效率会高点,但是会增加索引磁盘空间,insert的效率也会降低。

结论
我选择第二方式。但是设计表的时候,最好都加一个自增长的主键,存储结构会好一些,索引的效率也会好一些。

作者:一片-绿叶
来源:CSDN
原文:https://blog.csdn.net/weixin_41715077/article/details/82982530
版权声明:本文为博主原创文章,转载请附上博文链接!

<think>嗯,用户问的是Oracle中同时updateinsert一张会不会产生锁。我需要先回忆一下Oracle的锁机制。Oracle通常使用行级锁,这样在修改数据时只会锁定受影响的行,而不是整个。所以当执行UPDATE时,被修改的行会被加上行锁,防止其他事务同时修改这些行。同样,INSERT操作的时候,新插入的行也会被加上行锁,不过这时候可能更多的是排他锁,保证其他事务不会干扰新数据的插入。 接下来要考虑同时进行这两种操作的情况。假设一个事务在更新某些行,另一个事务在插入新行,这时候由于锁定的是不同的行,可能不会有冲突。但是如果两个操作都涉及到相同的行,比如某个INSERT操作触发了触发器,导致对已有行的UPDATE,这时候可能会出现锁等待的情况。另外,如果上有索引,尤其是主键或唯一索引,插入新行时可能会引起索引结构的调整,这时候Oracle可能会对索引块加锁,如果同时有UPDATE操作影响到同一索引块,就可能出现锁冲突。 还要考虑事务的隔离级别。比如,在默认的读已提交隔离级别下,事务在修改数据时会持有行锁直到事务结束,这可能导致其他事务需要等待。如果同时有大量的UPDATEINSERT操作,尤其是在高并发的情况下,可能会增加锁竞争的风险,甚至导致死锁。 比如,一个场景是,事务A在更新某行,持有该行锁,同时事务B试图插入一条新记录,如果这个插入操作需要修改某个索引块,而该索引块正好被事务A的更新操作锁住了,那么事务B可能需要等待。或者反过来,事务B插入数据导致索引块锁定,而事务A的更新操作需要访问同一索引块,从而被阻塞。 另外,如果上有外键约束,插入或更新数据时可能会检查外键,这时候可能会锁定父的行,也可能引入额外的锁。 还需要提到锁的类型,比如行级排他锁(RX)和共享锁(S)的区别。UPDATEINSERT通常使用排他锁,不允许其他事务同时修改同一行,但允许读取。而如果是使用FOR UPDATE这样的语句,可能会加更强的锁。 总结的话,应该告诉用户,一般情况下UPDATEINSERT操作在Oracle中不会互相阻塞,因为它们操作不同的行。但如果涉及到相同的行或索引结构,或者在事务中长时间持有锁,就可能出现锁的问题。同时,高并发或设计不当的事务逻辑可能导致死锁。建议用户检查具体的SQL语句、索引情况、事务隔离级别,以及是否存在触发器或约束,这些都可能影响锁的行为。使用监控工具如V$LOCK、V$SESSION等可以帮助诊断锁的问题。</think>在 Oracle 数据库中,当同时对同一执行 `UPDATE` 和 `INSERT` 操作时,是否会产生锁取决于具体操作的行和事务的隔离级别。以下是详细说明: --- ### **1. Oracle 的锁机制** Oracle 默认使用 **行级锁**(Row-Level Locking),即: - **`UPDATE`** 操作会锁定被修改的**目标行**(行级排他锁,Row Exclusive, RX)。 - **`INSERT`** 操作会锁定新插入的**新行**(同样是行级排他锁),同时可能短暂锁定的某些索引结构(如唯一索引)。 --- ### **2. `UPDATE` 和 `INSERT` 的锁行为** #### **场景 1:操作不同的行** - 如果 `UPDATE` 和 `INSERT` 操作**不涉及同一行**(例如 `INSERT` 新增一行,`UPDATE` 修改另一行),通常不会产生锁冲突。 - 因为行级锁仅作用于被操作的行,彼此独立。 #### **场景 2:操作同一行** - 若 `UPDATE` 和 `INSERT` 操作尝试修改同一行(例如通过触发器或唯一键冲突的逻辑),则会发生锁竞争。 - 例如:某个事务尝试 `UPDATE` 某行,而另一个事务试图 `INSERT` 一条可能触发唯一约束冲突的记录,此时 Oracle 可能会短暂锁定索引结构以检查冲突。 --- ### **3. 可能的锁冲突来源** #### **(1) 索引锁** - 如果有**唯一索引(Unique Index)**,`INSERT` 操作需要检查唯一性约束,可能短暂锁定索引块。 - 如果此时另一个事务正在 `UPDATE` 同一索引块中的行,可能发生锁等待(例如 `enq: TX - index contention`)。 #### **(2) 外键约束** - 若存在外键约束且未使用 `ON DELETE CASCADE`,`UPDATE` 父主键时可能锁定子相关行,进而影响子的 `INSERT`。 #### **(3) 事务隔离级别** - 在 `READ COMMITTED` 隔离级别(Oracle 默认)下,`UPDATE` 会持有行锁直到事务提交。 - 如果 `UPDATE` 和 `INSERT` 在同一个事务中,或事务未及时提交,可能延长锁持有时间。 --- ### **4. 死锁风险** - 如果多个事务以不同顺序操作行或索引,可能引发死锁。例如: 1. 事务 A `UPDATE` 行 1,并尝试 `INSERT` 行 2。 2. 事务 B `UPDATE` 行 2,并尝试 `INSERT` 行 1。 3. 此时可能发生死锁,Oracle 会自动检测并回滚其中一个事务。 --- ### **5. 如何监控锁?** 使用 Oracle 提供的系统视图诊断锁问题: - **`V$LOCK`**:查看当前锁信息。 - **`V$SESSION`**:关联会话与锁。 - **`V$SQL`**:查看正在执行的 SQL 语句。 示例查询: ```sql SELECT s.sid, s.serial#, s.username, l.type, l.lmode, l.block FROM v$session s JOIN v$lock l ON s.sid = l.sid WHERE s.type != 'BACKGROUND'; ``` --- ### **6. 最佳实践** 1. **减少事务时间**:尽快提交事务,缩短锁持有时间。 2. **合理设计索引**:避免过多唯一索引,或使用 `NOLOGGING` 减少索引维护开销。 3. **批量操作优化**:对大使用 `BULK INSERT` 或 `MERGE` 语句。 4. **避免热点行**:分散数据存储(例如哈希分区)。 --- ### **总结** - **一般情况下**,`UPDATE` 和 `INSERT` 操作同一但不同行时,不会因行级锁冲突。 - **可能引发锁的场景**:操作同一行、唯一索引冲突、外键约束、事务未提交或死锁。 - 建议通过监控工具定位具体锁问题,并结合业务逻辑优化设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值