日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

MySQL的insert into select 引发锁表

發布時間:2025/3/20 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL的insert into select 引发锁表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上周五HaC我要上線,有一個腳本需要執行,執行前需要備份一個表。

運維大佬:“這個表的備份為什么要這么久,,??”

1秒過去了……2秒過去了……

期間運營反饋系統出現大量訂單超時情況。

大佬找到我,問:“你怎么備份的?”

我:“insert into select * from 呀!”

大佬:“??你是不是不想混了?”

又是被大佬嫌棄的一天,為了不卷鋪蓋走人,我決定去學習一下表備份的常見方法。

MySQL一般我們在生產上備份數據通常會用到 這兩種方法:

  • INSERT INTO SELECT

  • CREATE TABLE AS SELECT

  • 注:本文僅針對MySQL innodb引擎,事務是可重復讀RR,數據庫版本為5.5

    1.INSERT INTO SELECT

    insert?into?Table2(field1,field2,...)?select?value1,value2,...?from?Table1

    注意

    (1)要求目標表Table2必須存在,并且字段field,field2…也必須存在

    (2)注意Table2的主鍵約束,如果Table2有主鍵而且不為空,則 field1, field2…中必須包括主鍵

    在執行語句的時候,MySQL是逐行加鎖的(掃描一個鎖一個),直至鎖住所有符合條件的數據,執行完畢才釋放鎖。所以當業務在進行的時候,切忌使用這種方法。

    在RR隔離級別下,還會加行鎖和間隙鎖

    舉個栗子吧:

    CREATE?TABLE?`t`?(`id`?int(11)?NOT?NULL?AUTO_INCREMENT,`c`?int(11)?DEFAULT?NULL,`d`?int(11)?DEFAULT?NULL,PRIMARY?KEY?(`id`),UNIQUE?KEY?`c`?(`c`) )?ENGINE=InnoDB;insert?into?t?values(null,?1,1); insert?into?t?values(null,?2,2); insert?into?t?values(null,?3,3); insert?into?t?values(null,?4,4);create?table?t2?like?t;

    執行

    begin; insert?into?t2(c,d)?select?c,d?from?t;

    先不commit;這個語句對表 t 主鍵索引加了 (-∞,1] 這個 next-key lock

    新開一個Navicat窗口,模擬新事務進入,此時執行下面這句sql就需要等待

    insert?into?t?values(-1,-1,-1); 鎖住了

    真就鎖表了~無法寫進去了,我終于知道為什么訂單超時了。

    背鍋背鍋。

    如果實在要使用 INSERT INTO SELECT 這種方法,可以使用下面的方法進行優化:

  • 加條件,強制走索引,不要全表掃描,例如

  • INSERT?INTO?Table2?SELECT*? FROMTable1?FORCE?INDEX?(create_time) WHEREupdate_time?<=?'2020-03-08?00:00:00';
  • 加上limit 100,100 這種,限制數量

  • 2. CREATE TABLE AS SELECT

    create table as select ?會創建一個不存在的表,也可以用來復制一個表。

    1.?create?table?t3?as?select?*?from?t?where?1=2; --?創建一個表結構與t一模一樣的表,只復制結構不復制數據;2.create?table?t3?as?select?*?from?t?; --?創建一個表結構與t一模一樣的表,復制結構同時也復制數據;(索引不會創建)3.create?table?t3(`id`,`a`)??as?select?`id`,`c`?from?t; --?創建一個表結構與t一模一樣的表,復制結構同時也復制數據,但是指定新表的列名;

    后面兩種格式,如果后面跟上合適的查詢條件,可以只復制符合條件的數據到新的表中。比如:

    create??table?table1??as??select?*?from?table2??where?columns1>=1;

    針對大表多字段的表復制,考慮是否每一個字段都是必需的,如果不是必需的,可以自定義選擇字段嗎,這樣復制的時間會大大提升。

    CREATE?table?table1?as?SELECT?id?FROM?table2;?--?只復制id這一列

    注意此建表過程全程鎖表。語句執行完畢,才釋放元數據鎖

    MDL全稱為metadata lock,即元數據鎖。MDL鎖主要作用是維護表元數據的數據一致性,在表上有活動事務(顯式或隱式)的時候,不可以對元數據進行寫入操作。因此從MySQL5.5版本開始引入了MDL鎖,來保護表的元數據信息,用于解決或者保證DDL操作與DML操作之間的一致性。

    注意:

  • 新表不會自動創建創建和原表相同的索引。(即復制表的索引會消失)

  • 3 .區別

    • 首先,最大的區別是二者屬于不同類型的語句,INSERT INTO SELECT 是DML語句(數據操作語言,SQL中處理數據等操作統稱為數據操縱語言),完成后需要提交才能生效,CREATE TABLE AS SELECT 是DDL語句(數據定義語言,用于定義和管理 SQL 數據庫中的所有對象的語言 ),執行完直接生效,不提供回滾,效率比較高。

    • 其次,功能不同,INSERT INTO SELECT只是插入數據,必須先建表;CREATE TABLE AS SELECT 則建表和插入數據一塊完成。

    • 當有大量數據的時候不推薦使用Insert into as,因為該語句的插入的效率很慢。

    4.總結

    以上對復制表來說,都不是很好的選擇,分享幾種平時常用的方法:

  • 導出成excel,然后拼sql 成 insert into values(),(),()的形式。

  • 定時任務,任務的邏輯是查詢100條記錄,然后多個線程分到幾個任務執行,比如是個線程,每個線程10條記錄,插入后,在查詢新的100條記錄處理。

  • mysqldumb方法,例如

    mysqldump?-h<span?class="katex-html"?aria-hidden="true" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;"><span?class="strut"?style="height:0.69444em;vertical-align:0em;" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;"><span?class="mord?mathit" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">h<span?class="mord?mathit" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">o<span?class="mord?mathit" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">s<span?class="mord?mathit" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">t<span?class="mord?mathit"?style="margin-right:0.05764em;" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">E<span?class="mord?mathit"?style="margin-right:0.05764em;" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">E<span?class="mord?mathit"?style="margin-right:0.13889em;" style="font-size: inherit;color: inherit;line-height: inherit;margin: 1px;overflow-wrap: inherit !important;word-break: inherit !important;">Pport?-u$user?--add-locks=0?--no-create-info?--single-transaction??--set-gtid-purged=OFF?db1?t?--where="a>900"?--result-file=/client_tmp/t.sql </span?class="mord?mathit"?style="margin-right:0.13889em;"></span?class="mord?mathit"?style="margin-right:0.05764em;"></span?class="mord?mathit"?style="margin-right:0.05764em;"></span?class="mord?mathit"></span?class="mord?mathit"></span?class="mord?mathit"></span?class="mord?mathit"></span?class="strut"?style="height:0.69444em;vertical-align:0em;"></span?class="katex-html"?aria-hidden="true">
  • 導出 CSV 文件

  • select?*?from?db1.t?where?a>900?into?outfile?'/server_tmp/t.csv';

    第3、4兩種方法適合整個表導出。

    5. 業務少的情況(深夜什么的)下,可以使用 create table as select ?。


    知識又增加了。

    原創電子書歷時整整一年總結的?Java 面試 + Java 后端技術學習指南,這是本人這幾年及校招的總結,各種高頻面試題已經全部進行總結,按照章節復習即可,已經拿到了大廠offer。 原創思維導圖掃碼或者微信搜?程序員的技術圈子?回復?面試?領取原創電子書和思維導圖。

    總結

    以上是生活随笔為你收集整理的MySQL的insert into select 引发锁表的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。