国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MYSQL不存在插入 存在更新的解決方法和對(duì)比

這篇具有很好參考價(jià)值的文章主要介紹了MYSQL不存在插入 存在更新的解決方法和對(duì)比。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

mysql存在更新不存在新增,mysql,數(shù)據(jù)庫(kù),java
設(shè)置主鍵id自增,name為唯一索引

一、避免重復(fù)插入

insert ignore into(有唯一索引)

關(guān)鍵字/句: insert ignore into,如果插入的數(shù)據(jù)會(huì)導(dǎo)致 UNIQUE索引PRIMARY KEY 發(fā)生沖突/重復(fù),則忽略此次操作/不插入數(shù)據(jù),例:

INSERT IGNORE INTO `student`(`name`,`age`) VALUES(`Jack`,18);

-- row(s) affected

這里已經(jīng)存在 name='Jack”的數(shù)據(jù),所以會(huì)忽略新插入的數(shù)據(jù),受影響行數(shù)為 0,表數(shù)據(jù)不變

需要注意 主鍵會(huì)自增

當(dāng)使用了insert ignore into 新增數(shù)據(jù),即使沒(méi)有插入,某些版本的mysql會(huì)自增主鍵。
比如原來(lái)有數(shù)據(jù)1(id為1),你又插入了數(shù)據(jù)1,但是重復(fù)了沒(méi)插入,之后再插入數(shù)據(jù)2,此時(shí)的數(shù)據(jù)2的主鍵為3而非2.
mysql5.7.26不會(huì)自增,8.0會(huì)自增

如何避免自增?

在MySQL5.7中做INSERT IGNORE時(shí)發(fā)現(xiàn), 即使INSERT未成功執(zhí)行, 表的自增主鍵卻自動(dòng)加1了, 在某些情況下需要避免這種行為. 需要修改的變量是 innodb_autoinc_lock_mode, 將其設(shè)為0后, 在INSERT未成功執(zhí)行時(shí)不會(huì)自增主鍵.

innodb_autoinc_lock_mode在MySQL各版本的默認(rèn)值

根據(jù)MySQL官方手冊(cè)的說(shuō)明:

There are three possible settings for the innodb_autoinc_lock_mode configuration parameter. The settings are 0, 1, or 2, for “traditional”, “consecutive”, or “interleaved” lock mode, respectively. As of MySQL 8.0, interleaved lock mode (innodb_autoinc_lock_mode=2) is the default setting. Prior to MySQL 8.0, consecutive lock mode is the default (innodb_autoinc_lock_mode=1).

在MySQL8中, 默認(rèn)值為 2 (interleaved, 交錯(cuò)), 在MySQL8以前, 準(zhǔn)確地說(shuō)在8之前, 5.1之后, 默認(rèn)值為 1 (consecutive, 連續(xù)), 在更早的版本是 0

innodb_autoinc_lock_mode的說(shuō)明

這個(gè)值主要用于平衡性能與安全(主從的數(shù)據(jù)一致性), insert主要有以下類型

simple insert 如insert into t(name) values(‘test’)
bulk insert 如load data | insert into … select … from …
mixed insert 如insert into t(id,name) values(1,‘a(chǎn)’),(null,‘b’),(5,‘c’);
innodb_autoinc_lock_mode = 0:

與更高版本的MySQL向后兼容
在這一模式下,所有的insert語(yǔ)句都要在語(yǔ)句開(kāi)始的時(shí)候得到一個(gè)表級(jí)的auto_inc鎖,在語(yǔ)句結(jié)束的時(shí)候才釋放這把鎖,一個(gè)事務(wù)可能包涵有一個(gè)或多個(gè)語(yǔ)句
它能保證值分配的可預(yù)見(jiàn)性,與連續(xù)性,可重復(fù)性,這個(gè)也就保證了insert語(yǔ)句在復(fù)制到slave的時(shí)候還能生成和master那邊一樣的值(它保證了基于語(yǔ)句復(fù)制的安全)
由于在這種模式下auto_inc鎖一直要保持到語(yǔ)句的結(jié)束,所以這個(gè)就影響到了并發(fā)的插入
innodb_autoinc_lock_mode = 1:

這一模式對(duì)simple insert做了優(yōu)化,由于simple insert一次性插入值的個(gè)數(shù)可以立即確定, 所以mysql可以一次生成幾個(gè)連續(xù)的值用于這個(gè)insert語(yǔ)句, 總的來(lái)說(shuō)這個(gè)對(duì)復(fù)制也是安全的(保證了基于語(yǔ)句復(fù)制的安全)
這一模式也是MySQL8.0之前的默認(rèn)模式, 這個(gè)模式的好處是auto_inc鎖不要一直保持到語(yǔ)句的結(jié)束, 只要語(yǔ)句得到了相應(yīng)的值后就可以提前釋放鎖
innodb_autoinc_lock_mode = 2:

由于這個(gè)模式下已經(jīng)沒(méi)有了auto_inc鎖, 所以這個(gè)模式下的性能是最好的, 但是它也有一個(gè)問(wèn)題, 就是對(duì)于同一個(gè)語(yǔ)句來(lái)說(shuō)它所得到的auto_incremant值可能不是連續(xù)的
現(xiàn)在mysql已經(jīng)推薦把二進(jìn)制的格式設(shè)置成row, 所以在binlog_format不是statement的情況下這個(gè)模式可以達(dá)到最好的性能

insert if not exists(無(wú)唯一索引)

數(shù)據(jù)字段沒(méi)有設(shè)置主鍵或唯一索引,當(dāng)插入數(shù)據(jù)時(shí),首先判斷是否存在這條數(shù)據(jù),不存在正常插入,存在則忽略?,F(xiàn)在我把主鍵和唯一索引都去掉了。完整sql為

# 示例一:插入多條記錄,假設(shè)有一個(gè)主鍵為 client_id 的 clients 表,可以使用下面的語(yǔ)句:

INSERT INTO clients (client_id,client_name,client_type)
SELECT supplier_id,supplier_name,’advertising’
FROM suppliers
WHERE not exists
(select * from clients
where clients.client_id = suppliers.supplier_id);

#示例二:插入單條記錄
INSERT INTO clients(client_id,client_name,client_type)
SELECT 10345,’IBM’,’advertising’
FROM dual
WHERE not exists
(select*from clients
where clients.client_id=10345
);

二、不存在則插入,存在則更新

on duplicate key update

如果插入的數(shù)據(jù)會(huì)導(dǎo)致UNIQUE 索引或PRIMARY KEY發(fā)生沖突/重復(fù),則執(zhí)行UPDATE語(yǔ)句,例:

#name 有唯一索引
INSERT INTO `student`(`name`, `age`) VALUES('Jack', 19)
  ON DUPLICATE KEY  UPDATE `age`=19; 
  -- If will happen conflict, the update statement is executed

-- 2 row(s) affected

這里受影響的行數(shù)是2,因?yàn)閿?shù)據(jù)庫(kù)中存在name='Jack’的數(shù)據(jù),如果不存在此條數(shù)據(jù),則受影響的行數(shù)為1

可能遇到死鎖

bug在5.7.26以及8.0.15版本上已經(jīng)修復(fù)了,當(dāng)插入數(shù)據(jù)時(shí),不會(huì)在形成間隙鎖

但是此方法也有坑,如果表中不止一個(gè)唯一索引的話,在特定版本的mysql中容易產(chǎn)生dead lock(死鎖)

當(dāng)mysql執(zhí)行INSERT ON DUPLICATE KEY的 INSERT時(shí),存儲(chǔ)引擎會(huì)檢查插入的行是否會(huì)產(chǎn)生重復(fù)鍵錯(cuò)誤。如果是的話,它會(huì)將現(xiàn)有的
行返回給mysql,mysql會(huì)更新它并將其發(fā)送回存儲(chǔ)引擎。當(dāng)表具有多個(gè)唯一或主鍵時(shí),此語(yǔ)句對(duì)存儲(chǔ)引擎檢查密鑰的順序非常敏感。根據(jù)這個(gè)順序,
存儲(chǔ)引擎可以確定不同的行數(shù)據(jù)給到mysql,因此mysql可以更新不同的行。存儲(chǔ)引擎檢查key的順序不是確定性的。例如,InnoDB按照索引添加到
表的順序檢查鍵。

insert … on duplicate key 在執(zhí)行時(shí),innodb引擎會(huì)先判斷插入的行是否產(chǎn)生重復(fù)key錯(cuò)誤,如果存在,在對(duì)該現(xiàn)有的行加上S(共享鎖)鎖,如果返回該行數(shù)據(jù)給mysql,然后mysql執(zhí)行完duplicate后的update操作,然后對(duì)該記錄加上X(排他鎖),最后進(jìn)行update寫入。
如果有兩個(gè)事務(wù)并發(fā)的執(zhí)行同樣的語(yǔ)句,那么就會(huì)產(chǎn)生death lock

mysql官方描述很簡(jiǎn)單

An INSERT … ON DUPLICATE KEY UPDATE statement against a table having more than one unique or primary key is also marked as unsafe. (Bug #11765650, Bug #58637)

insert on duplicate key update 如果命中主鍵或者唯一鍵索引,加行鎖,未命中加gap鎖,即會(huì)阻塞插入數(shù)據(jù)
mysql存在更新不存在新增,mysql,數(shù)據(jù)庫(kù),java
過(guò)程分析
insert … on duplicate key 在執(zhí)行時(shí),innodb引擎會(huì)先判斷插入的行是否產(chǎn)生重復(fù)key錯(cuò)誤,如果存在,在對(duì)該現(xiàn)有的行加上S(共享鎖)鎖,如果返回該行數(shù)據(jù)給mysql,然后mysql執(zhí)行完duplicate后的update操作,然后對(duì)該記錄加上X(排他鎖),最后進(jìn)行update寫入。
如果有兩個(gè)事務(wù)并發(fā)的執(zhí)行同樣的語(yǔ)句,那么就會(huì)產(chǎn)生death lock,如:
mysql存在更新不存在新增,mysql,數(shù)據(jù)庫(kù),java
低版本的解決方法

  1. 盡量不對(duì)存在多個(gè)唯一鍵的table使用該語(yǔ)句
  2. 在有可能有并發(fā)事務(wù)執(zhí)行的insert 的內(nèi)容一樣情況下不使用該語(yǔ)句。將批量insert on duplicate key update,拆分成多個(gè)語(yǔ)句。保證一次事務(wù)中不要插入過(guò)多值,將多個(gè)數(shù)據(jù),變成多個(gè)sql,執(zhí)行插入??梢杂行У臏p少死鎖命中的發(fā)生。
  3. 重試:死鎖不可怕,當(dāng)出現(xiàn)死鎖發(fā)生時(shí),多執(zhí)行重試操作可以有效保證插入成功,更新不丟失。
  4. 線程池多線程并發(fā)執(zhí)行改為單線程排隊(duì)處理。

replace into(先刪除再插入)

mysql存在更新不存在新增,mysql,數(shù)據(jù)庫(kù),java
replace into 會(huì)根據(jù)唯一索引或主鍵進(jìn)行判斷,如果存在則覆蓋寫入字段,如果不存在則新增。
此方法有坑,如果主鍵是自增的,且通過(guò)唯一索引來(lái)進(jìn)行操作時(shí),主鍵會(huì)變更,該方法底層是先進(jìn)性delete,在insert
如果有子表依賴的話不建議使用。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-786925.html

到了這里,關(guān)于MYSQL不存在插入 存在更新的解決方法和對(duì)比的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • mysql插入數(shù)據(jù)如果存在則忽略

    經(jīng)常有一種場(chǎng)景,某類數(shù)據(jù)只能在一張表中存在一條,我們會(huì)創(chuàng)建唯一索引進(jìn)行約束,但是如果重復(fù)插入就報(bào)錯(cuò)了,所以開(kāi)發(fā)上一版都會(huì)先查一次然后再insert。 mysql有個(gè)簡(jiǎn)單的寫法,基于已經(jīng)創(chuàng)建的索引,如果存在的話,那么就忽略這條記錄的插入。 不廢話了,上代碼吧。

    2023年04月12日
    瀏覽(22)
  • 寶塔 檢測(cè)到系統(tǒng)已存在mysql 請(qǐng)使用純凈安裝 【有效的解決方法】

    advance2016 于 2023-03-21 14:47:50 發(fā)布 1)以管理員的身份運(yùn)行CMD 執(zhí)行命令: sc delete mysql 1 sc delete mysql 2)清除注冊(cè)表: 在文件資源管理器中輸入“C:Windowsregedit.exe\\\"彈出注冊(cè)表 刪除HKEY_LOCAL_MACHINESYSTEMControlSet001ServicesEventlogApplicationMySQL文件夾 如果能找到如下內(nèi)容,刪除 HKEY_L

    2024年02月07日
    瀏覽(15)
  • MySQL不同插入方式性能對(duì)比實(shí)驗(yàn)

    MySQL不同插入方式性能對(duì)比實(shí)驗(yàn)

    最近負(fù)責(zé)的項(xiàng)目需要數(shù)據(jù)同步入庫(kù)MySQL,為了測(cè)速那種入庫(kù)方式效率比較高,為此進(jìn)行了以下的對(duì)比實(shí)驗(yàn),在此記錄一下 共三種方法對(duì)比 一條一條插入,最后一次提交 用for循環(huán)拼接好插入sql,一次執(zhí)行 使用MySQL提供的方法executeBatch(),同樣使用一次提交 mutiSqlInsert singleSqlIn

    2024年01月22日
    瀏覽(15)
  • 云原生數(shù)據(jù)倉(cāng)庫(kù)AnalyticDB Mysql(ADB分析型數(shù)據(jù)庫(kù))-DML語(yǔ)法之新增插入數(shù)據(jù)詳解

    ADB分析型數(shù)據(jù)庫(kù),是阿里云平臺(tái)上資源,原名叫云原生數(shù)據(jù)倉(cāng)庫(kù)AnalyticDB Mysql,俗稱ADB分析型數(shù)據(jù)庫(kù),那么ADB的語(yǔ)法與mysql關(guān)系型數(shù)據(jù)庫(kù)語(yǔ)法存在一定的差異。 本文為筆記,介紹ADB的DML語(yǔ)法的應(yīng)用。 1. INSERT INTO INSERT INTO用于向表中插入數(shù)據(jù),主鍵重復(fù)時(shí)會(huì)自動(dòng)忽略當(dāng)前寫入數(shù)據(jù)

    2024年02月15日
    瀏覽(18)
  • Springboot Mybatis 不存在插入數(shù)據(jù),存在則更新數(shù)據(jù)

    Springboot Mybatis 不存在插入數(shù)據(jù),存在則更新數(shù)據(jù)

    是不是經(jīng)常看到代碼, 查一下數(shù)據(jù)庫(kù),如果存在數(shù)據(jù),就做更新語(yǔ)句調(diào)用; 如果不存在,就插入。 今天該篇介紹的 是使用? ? ?INSERT INTO ? ? ? ?ON DUPLICATE KEY UPDATE ? ? ? ?來(lái)實(shí)現(xiàn)我們上述的場(chǎng)景, 不需要自己再判斷來(lái)判斷去的。 ON DUPLICATE key update 是根據(jù)主鍵索引或者唯一

    2024年02月13日
    瀏覽(24)
  • 記錄線上一次mysql只能查詢,不能插入或更新的bug

    記錄線上一次mysql只能查詢,不能插入或更新的bug

    錯(cuò)誤復(fù)現(xiàn) 突然有一天產(chǎn)品通知xx服務(wù)不可用,想著最近也沒(méi)有服務(wù)更新,就先排查一下服務(wù)日志 使用postman測(cè)試的時(shí)候請(qǐng)求明顯超時(shí),查看日志顯示是一個(gè)鎖的問(wèn)題 使用工具連接到mysql,查看information_schema.INNODB_TRX,發(fā)現(xiàn)有一個(gè)事務(wù)處于Running的狀態(tài),查看id后不能刪除。 查看

    2024年02月13日
    瀏覽(25)
  • JAVA實(shí)現(xiàn)存在更新不存在插入與及多余的進(jìn)行刪除(三)

    這個(gè)版本,主要是迭代重載了下save方法,不廢話,直接上代碼: 具體實(shí)現(xiàn)類對(duì)應(yīng)的重載方法如下: 然后就是頭部加多了 implements ICudDataServiceT, ApplicationContextAware。 通過(guò)這個(gè)ApplicationContextAware獲取到所有bean服務(wù),膚淺地以實(shí)體類拼湊一下服務(wù)名,找到bean服務(wù)就作為這個(gè)調(diào)用的

    2024年02月13日
    瀏覽(46)
  • PostgreSQL 分區(qū)表插入數(shù)據(jù)及報(bào)錯(cuò):子表明明存在卻報(bào)不存在以及column “xxx“ does not exist 解決方法

    PostgreSQL 分區(qū)表插入數(shù)據(jù)及報(bào)錯(cuò):子表明明存在卻報(bào)不存在以及column “xxx“ does not exist 解決方法

    記錄分區(qū)表插入遇到的倆個(gè)問(wèn)題: 這個(gè)問(wèn)題可真的是,太難查了,倆個(gè)sql看著一模一樣,但就是一個(gè)報(bào)錯(cuò),一個(gè)不報(bào)錯(cuò);只有導(dǎo)入的文件有差別,猜測(cè)是文件的原因; 但具體是什么呢?來(lái)實(shí)錘下 錯(cuò)誤的文件前面有非法字符:uFEFF ; 怎么解決呢?代碼兼容, 1. 每次替換下非法

    2024年01月16日
    瀏覽(25)
  • Mysql大數(shù)據(jù)批量插入方法

    MySQL是當(dāng)前最流行的關(guān)系型數(shù)據(jù)庫(kù)之一,大數(shù)據(jù)批量插入是MySQL中常用的操作之一。在處理大量數(shù)據(jù)時(shí),如果一條一條地插入會(huì)極大地影響效率,因此批量插入是一個(gè)更好的選擇,可以大大提高數(shù)據(jù)的處理速度。下面介紹幾種MySQL大數(shù)據(jù)批量插入的方法。 使用LOAD DATA INFILE語(yǔ)句

    2024年02月10日
    瀏覽(18)
  • MybatisPlus 使用 saveOrUpdate 詳解(慎用),及問(wèn)題解決方法&mysql保存或更新 ON DUPLICATE KEY UPDATE

    MybatisPlus 使用 saveOrUpdate 詳解(慎用),及問(wèn)題解決方法&mysql保存或更新 ON DUPLICATE KEY UPDATE

    今天的想法是,要在插入數(shù)據(jù)庫(kù)時(shí),如果有某某一個(gè)主要字段的值重復(fù),則不插入,否則則插入! 看了一下mybatis-Plus是有這個(gè)saveOrUpdate 方法! 原本使用save時(shí)是沒(méi)有問(wèn)題了,改成saveOrUpdate 用了一下就報(bào)錯(cuò)了。 com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: error: can not execut

    2024年02月11日
    瀏覽(42)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包