盡量申請自增 id 后筑悴,釋放自增鎖(上一篇)。
insert 輕量對普通才有效稍途。有些 insert :其他資源加鎖阁吝,申請自增 id 后,不能馬上釋放械拍。
一突勇、insert … select 語句
可重復(fù)讀隔離級別binlog_format=statement:insert into? t2(c,d) select c,d from t;
所有行和間隙加鎖,保證日志和數(shù)據(jù)一致性甲馋。執(zhí)行序列:
B先執(zhí)行埂奈, t 主鍵索引加了 (-∞,1] 這個 next-key lock,執(zhí)行完A 的 insert 執(zhí)行定躏。
沒有鎖账磺,B 的 insert先執(zhí)行,后寫入 binlog痊远。binlog_format=statement 垮抗,binlog 里面就記錄了這樣的語句序列:
insert into t? values(-1,-1,-1);
insert into? t2(c,d) select c,d from t;
到了備庫執(zhí)行,把 id=-1 寫到表 t2 中碧聪,主備不一致冒版。
二、insert 循環(huán)寫入
insert …select 只鎖需訪問資源逞姿,不是鎖全表辞嗡。
2.1?insert into?t2?掃描行數(shù)Rows_examined=1,受 limit 1 影響
insert into? t2(c,d)? (select c+1, d from t force? index(c) order by c desc limit 1);? ?//插入一行數(shù)據(jù)哼凯, c 值= c 最大值+ 1欲间。
加鎖范圍:?索引 c 上 (3,4] 和 (4,supremum]這兩個 next-key lock,主鍵索引 id=4 這行断部。
索引 c 倒序猎贴,掃描第一行,結(jié)果寫入 t2 蝴光。
2.2 插入表 t :Rows_examined = 5? 她渴,用臨時表
insert into? t(c,d)? (select c+1, d from t force? index(c) order by c desc limit 1);?
Using temporary用臨時表:t 內(nèi)容讀出蔑祟,寫入臨時表趁耗。
rows =1,猜測:子查詢結(jié)果讀出來(掃描 1 行)疆虚,寫入臨時表苛败,從臨時表讀出來(掃描 1 行),寫回表 t 中径簿。掃描行數(shù) 2(不是5)罢屈,猜測不對。
2.3 用臨時表原因
邊遍歷邊更新篇亭,讀出直接寫回原表缠捌,遍歷過程,讀到剛插記錄(如果參與計算邏輯译蒂,跟語義不符)曼月。
Innodb_rows_read增加 4谊却。 Memory 全表掃描表 t。
1. 創(chuàng)建臨時表哑芹,字段 c 和 d
2.? 索引 c 掃描表 t炎辨,依次取 c=4、3绩衷、2蹦魔、1回表,讀到 c 和 d 寫入臨時表咳燕。Rows_examined=4勿决。
3.? ?limit 1,只取臨時表第一行招盲,插入 t 低缩。Rows_examined加 1,= 5曹货。
索引 c 上間隙都加上共享 next-key lock咆繁。其他事務(wù)不能insert。
2.4 優(yōu)化辦法
1:沒在子查詢中直接使用 limit 1顶籽,遍歷整表 玩般。應(yīng)先 insert into臨時表 temp_t,只需要掃描一行礼饱;取出插入t1坏为。
2:數(shù)據(jù)量小,用內(nèi)存臨時表:
三镊绪、insert 唯一鍵沖突
可重復(fù)讀(repeatable read)匀伏。 B insert 鎖等待。
A 唯一鍵沖突蝴韭,沖突索引上加鎖够颠。 next-key lock 由右邊界值定義。 A 持有索引 c 上 (5,10] 共享 next-key lock(讀鎖)榄鉴。
主鍵履磨、唯一索引沖突加都 next-key lock。加讀鎖庆尘,避免這行被別的事務(wù)刪掉蹬耘。
3.1 經(jīng)典死鎖場景
session A rollback 時,C 幾乎同時發(fā)現(xiàn)死鎖并返回减余。
1.? T1 ,啟動? A惩系,insert 語句位岔,索引c=5 加記錄鎖如筛。c是唯一索引,退化為記錄鎖(如果你的印象模糊了抒抬,可以回顧下第 21 篇文章介紹的加鎖規(guī)則)杨刨。
2.? T2 , B 相同 insert 語句擦剑,唯一鍵沖突妖胀,加讀鎖?惠勒; C 也在索引c 上赚抡,c=5 記錄上加讀鎖。
3.? T3 時刻纠屋,A 回滾涂臣。 B 和 C 執(zhí)行插入操作,加寫鎖售担。等待對方行鎖赁遗,死鎖。
四族铆、insert into … on duplicate?key update
主鍵沖突后直接報錯岩四,如改寫成
insert into t? values(11,10,10)?on?duplicate key update?d=100;? 給索引 c 上 (5,10]?加排他 next-key lock(寫鎖)。
插入碰到唯一鍵約束哥攘,執(zhí)行后面更新語句剖煌。
多個列違反了唯一性約束,按照索引的順序献丑,修改跟第一個索引沖突的行末捣。
已有 (1,1,1) 和 (2,2,2)
先判斷主鍵 id 是的,跟 id=2 這一行沖突创橄,修改 id=2 行箩做。
需要注意的是,執(zhí)行這條語句affected rows 返回的是 2妥畏,很容易造成誤解邦邦。真正更新的只有一行,insert 和 update 都認為自己成功了醉蚁,計數(shù)都加1
小結(jié)
insert … select 拷貝數(shù)據(jù)燃辖。可重復(fù)讀, select 掃描記錄的間隙加讀鎖网棍。
insert 和 select 對象是同一個表黔龟,循環(huán)寫入。引入用戶臨時表做優(yōu)化。
insert 唯一鍵沖突氏身,沖突唯一值上加共享 next-key lock(S 鎖)巍棱。盡快提交或回滾事務(wù),避免加鎖時間長蛋欣。
問題
兩個表之間拷貝數(shù)據(jù)什么方法航徙,注意事項?優(yōu)勢陷虎?
下一篇文章到踏。