事務相關
什么是事務?
事務:是由一組SQL語句組成的邏輯處理單元,事務具有以下4個屬性,通常簡稱為事務。事務的ACID屬性:
(1)原子性(Atomicity):
事務是一個原子操作單元,事務包含的所有操作要么全部成功,要么全部失敗回滾,因此事務的操作如果成功就必須要完全應用到數據庫,如果操作失敗則不能對數據庫有任何影響。(2)一致性(Consistent):
在事務開始和完成時,數據都必須保持一致狀態。這意味著所有相關的數據規則都必須應用于事務的修改,以保持數據的完整性;事務結束時,所有的內部數據結構(如B樹索引或雙向鏈表)也都必須是正確的。
一致性是指事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態,也就是說一個事務執行之前和執行之后都必須處于一致性狀態。
例如轉賬,假設用戶A和用戶B兩者的錢加起來一共是5000,那么不管A和B之間如何轉賬,轉幾次賬,事務結束后兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。(3)隔離性(Isolation):
數據庫系統提供一定的隔離機制,保證事務在不受外部并發操作影響的“獨立”環境執行。這意味著事務處理過程中的中間狀態對外部是不可見的,反之亦然。
隔離性是當多個用戶并發訪問數據庫時,比如操作同一張表時,數據庫為每一個用戶開啟的事務,不能被其他事務的操作所干擾,多個并發事務之間要相互隔離。
? ? ? ?即要達到這么一種效果:對于任意兩個并發的事務T1和T2,在事務T1看來,T2要么在T1開始之前就已經結束,要么在T1結束之后才開始,這樣每個事務都感覺不到有其他事務在并發地執行。(4)持久性(Durable):
事務完成之后,它對于數據的修改是永久性的,即使出現系統故障也能夠保持。
持久性是指一個事務一旦被提交了,那么對數據庫中的數據的改變就是永久性的,即便是在數據庫系統遇到故障的情況下也不會丟失提交事務的操作。Mysql中會保存有相應的操作日志,即使遭遇故障依然能夠通過日志恢復最后一次更新。
例如我們在使用JDBC操作數據庫時,在提交事務方法后,提示用戶事務操作完成,當我們程序執行完成直到看到提示后,就可以認定事務以及正確提交,即使這時候數據庫出現了問題,也必須要將我們的事務完全執行完成,否則就會造成我們看到提示事務處理完畢,但是數據庫因為故障而沒有執行事務的重大錯誤。簡單理解:事務由一個或多個sql語句組成一個整體;
? ? 在事務中的操作,要么都執行修改,要么都不執行,
? ? 只有在該事務中所有的語句都執行成功才會將修改加入到數據庫中,否則回滾到上一步。
Mysql實現事務
# start transaction; # 啟動事務:
# update from account set money=money-100 where name='a';
# update from account set money=money+100 where name='b';
# commit; # 手動關閉事務'
MySQL的事務隔離級別
- 未提交讀(Read Uncommitted):允許臟讀,其他事務只要修改了數據,即使未提交,本事務也能看到修改后的數據值。也就是可能讀取到其他會話中未提交事務修改的數據
- 提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重復讀)。
- 可重復讀(Repeated Read):可重復讀。無論其他事務是否修改并提交了數據,在這個事務中看到的數據值始終不受其他事務影響。
- 串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞
MySQL數據庫(InnoDB引擎)默認使用可重復讀( Repeatable read)
事務的并發問題
- 臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據
- 不可重復讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新并提交,導致事務A多次讀取同一數據時,結果 不一致。
- 幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
小結:不可重復讀的和幻讀很容易混淆,不可重復讀側重于修改,幻讀側重于新增或刪除。解決不可重復讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表
事務隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
讀未提交(read-uncommitted) | 是 | 是 | 是 |
不可重復讀(read-committed) | 否 | 是 | 是 |
可重復讀(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |
索引和約束
mysql 每個表最多16個約束
詳細請參考:https://blog.csdn.net/fenglepeng/article/details/103141756
數據庫五大約束
primary KEY:設置主鍵約束;
UNIQUE:設置唯一性約束,不能有重復值;
DEFAULT 默認值約束 ? ?
NOT NULL:設置非空約束,該字段不能為空;
FOREIGN key :設置外鍵約束。
MySQL索引種類
- 普通索引:僅加速查詢
- 唯一索引:加速查詢 + 列值唯一(可以有null)
- 主鍵索引:加速查詢 + 列值唯一 + 表中只有一個(不可以有null)
- 組合索引:多列值組成一個索引,專門用于組合搜索,其效率大于索引合并
- 全文索引:對文本的內容進行分詞,進行搜索
# 其他
? ? 1、索引合并:利用多個單列索引查詢
? ? 2、覆蓋索引:在索引表中就能將想要的數據查詢到
什么是索引合并?
# 索引合并訪問方法可以在查詢中對一個表使用多個索引,對它們同時掃描,并且合并結果。
# 此訪問方法合并來自單個表的索引掃描; 它不會將掃描合并到多個表中。
什么是覆蓋索引?
# 解釋一:
就是select的數據列只用從索引中就能夠取得,不必從數據表中讀取,換句話說查詢列要被所使用的索引覆蓋。
# 解釋二:
索引是高效找到行的一個方法,當能通過檢索索引就可以讀取想要的數據,那就不需要再到數據表中讀取行了。
如果一個索引包含了(或覆蓋了)滿足查詢語句中字段與條件的數據就叫做覆蓋索引。
# 注意:MySQL只能使用B-Tree索引做覆蓋索引
索引在什么情況下遵循最左前綴的規則?
主鍵和外鍵的區別?
'主鍵'
? ? 唯一標識一條記錄
? ? 用來保證數據的完整性
? ? 主鍵只能有一個
'外鍵'
? ? 表的外鍵是另一個表的主鍵,外鍵可以有重復的,可以是空值
? ? 用來和其他表建立聯系用的
? ? 一個表可以有多個外鍵
列舉創建索引但是無法命中索引的8種情況。
使用'like ‘%xx’';select * from tb1 where name like '%cn';
使用'函數';select * from tb1 where reverse(name)='zgc';
使用'or';select * from tb1 where nid=1 or ?email='zgc@gmial.com';
? ? ? 特別的:當or條件中有未建立索引的列才失效,以下會走索引
? ? ? ? ? ? # select * from tb1 where nid=1 or name='zgc';
? ? ? ? ? ? # select * from tb1 where nid=1 or email='zgc@gmial.com' and name='zgc';
類型不一致,如果列是字符串類型,傳入條件是必須用引號引起來,不然則可能會無法命中
? ? select * from tb1 where name=666;
含有'!= ';?select * from tb1 where name != 'zgc';
? ? 特別的:如果是主鍵,還是會走索引;select * from tb1 where nid != 123;
含有'>';select * from tb1 where name > 'zgc';
? ? 特別的:如果是主鍵或者索引是整數類型,則還是會走索引
? ? ? ? ? ? # select * from tb1 where nid > 123;
? ? ? ? ? ? # select * from tb1 where name > 123;
含有'order by';select email from tb1 order by name desc;
? ? 當根據索引排序時,選擇的映射如果不是索引,則不走索引
? ? 特別的:如果對主鍵排序,則還是走索引:
? ? ? ? ? ? # select * from tb1 order by nid desc;#組合索引最左前綴
? ? 如果組合索引為:(name,email)
? ? name and email # 使用索引
? ? name ? ? ? ? ? # 使用索引
? ? email ? ? ? ? ?# 不使用索引
在對name做了唯一索引前提下,簡述以下區別:
select * from tb where name = ‘小明’
select * from tb where name = ‘小明’ limit 1
沒做唯一索引的話,前者查詢會全表掃描,效率低些
limit 1,只要找到對應一條數據,就不繼續往下掃描.
然而 name 字段添加唯一索引了,加不加limit 1,意義都不大;
1000w條數據,使用limit offset 分頁時,為什么越往后翻越慢?如何解決?
例如:
#limit 100000,20; 從第十萬條開始往后取二十條,
#limit 20 offset 100000; limit后面是取20條數據,offset后面是從先掃描前10w行,然后從10W條數據開始讀
因為當一個數據庫表過于龐大,LIMIT offset, length中的offset值過大,則SQL查詢語句會非常緩慢
--------------------------------------------------------------------------
'優化一'
先查看主鍵,再分頁:
select * from tb where id in (select id from tb where limit 10 offset 30)
--------------------------------------------------------------------------
'優化二'
記錄當前頁,數據、ID、最大值和最小值(用于where查詢)
在翻頁時,根據條件進行篩選,篩選完畢后,再根據 limit offset 查詢
select * from(select * from tb where id > 2222) as B limit 10 offset 0;
# 如果用戶自己修改頁碼,也可能導致變慢,此時可以對 url 頁碼進行加密,例如rest framework
--------------------------------------------------------------------------
'優化三'
可以按照當前業務需求,看是否可以設置只允許看前200頁;
一般情況下,沒人會咔咔看個幾十上百頁的;
MySQL中InnoDB引擎的行鎖是通過加在什么上完成(或稱實現)的?
InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。InnoDB這種行鎖實現特點意味著:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!
InnoDB存儲引擎MVCC的實現策略
MVCC的實現,通過保存數據在某個時間點的快照來實現的。這意味著一個事務無論運行多長時間,在同一個事務里能夠看到數據一致的視圖。根據事務開始的時間不同,同時也意味著在同一個時刻不同事務看到的相同表里的數據可能是不同的。
innodb:在每一行數據中額外保存兩個隱藏的列:當前行創建時的版本號和刪除時的版本號(可能為空,其實還有一列稱為回滾指針,用于事務回滾,不在本文范疇)。這里的版本號并不是實際的時間值,而是系統版本號。每開始新的事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會作為事務的版本號,用來和查詢每行記錄的版本號進行比較。
每個事務又有自己的版本號,這樣事務內執行CRUD操作時,就通過版本號的比較來達到數據版本控制的目的。
索引與鎖有什么關系?
沒有建立索引的話我們在進行數據選取或者定位的時候是通過全表掃描的形式來進行的,比如存在這樣一張表user(id,name,phone,address);并且這張表中并沒有任何索引,那么sql:delete from user where name='張三' 這樣一個語句是如何定義到張三這個記錄的,因為沒有索引,所以在數據庫實現的時候是對整張表進行掃描的,那么數據庫是不是會把整張表鎖定起來。
?
在mysql中的鎖看起來是很復雜的,因為有一大堆的東西和名詞:排它鎖,共享鎖,表鎖,頁鎖,間隙鎖,意向排它鎖,意向共享鎖,行鎖,讀鎖,寫鎖,樂觀鎖,悲觀鎖,死鎖。這些名詞有的博客又直接寫鎖的英文的簡寫--->X鎖,S鎖,IS鎖,IX鎖,MMVC...
對于UPDATE、DELETE、INSERT語句,InnoDB會自動給涉及數據集加排他鎖(X)
MyISAM在執行查詢語句SELECT前,會自動給涉及的所有表加讀鎖,在執行更新操作(UPDATE、DELETE、INSERT等)前,會自動給涉及的表加寫鎖,這個過程并不需要用戶干預
數據庫事務有不同的隔離級別,不同的隔離級別對鎖的使用是不同的,鎖的應用最終導致不同事務的隔離級別
MVCC(Multi-Version Concurrency Control)多版本并發控制,可以簡單地認為:MVCC就是行級鎖的一個變種(升級版)。
事務的隔離級別就是通過鎖的機制來實現,只不過隱藏了加鎖細節
在表鎖中我們讀寫是阻塞的,基于提升并發性能的考慮,MVCC一般讀寫是不阻塞的(所以說MVCC很多情況下避免了加鎖的操作)
MVCC實現的讀寫不阻塞正如其名:多版本并發控制--->通過一定機制生成一個數據請求時間點的一致性數據快照(Snapshot),并用這個快照來提供一定級別(語句級或事務級)的一致性讀取。從用戶的角度來看,好像是數據庫可以提供同一數據的多個版本。
表中字段建立索引應該遵循幾個原則:
- 1)越小的數據類型通常更好:越小的數據類型通常在磁盤、內存中都需要更少的空間,處理起來更快。
- 2)簡單的數據類型更好:整型數據比起字符,處理開銷更小,因為字符串的比較更復雜,處理起來也更耗時。
- 3)盡量避免NULL:應該指定列為NOT NULL。含有空值的列很難進行查詢優化,因為它們使得索引、索引的統計信息以及比較運算更加復雜。你應該用0、一個特殊的值或者一個空串代替空值。
- 4)對非唯一的字段,例如“性別”這種大量重復值的字段,增加索引也沒有什么意義,所以索引的建立應當更多的選取唯一性更高的字段。
1、列舉常見的關系型數據庫和非關系型都有那些?
關系型:sqllite、db2、oracle、access、SQLserver、MySQL
?????# 注意:sql語句通用,需要有表結構
非關系型:mongodb、redis、memcache
????# 非關系型數據庫是key-value存儲的,沒有表結構。
2、MySQL常見數據庫引擎
MySQL有多種存儲引擎:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE
3、MyISAM 和 InnoDB 的區別
1)事務支持:
? ???MyISAM:強調的是性能,每次查詢具有原子性,其執行數度比InnoDB類型更快,但是不提供事務支持。
?????InnoDB:提供事務支持事務,外部鍵等高級數據庫功能。 具有事務(commit)、回滾(rollback)和崩潰修復能力(crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。2)MyISAM適合查詢以及插入為主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用。
3)InnoDB支持外鍵,MyISAM不支持。InnoDB支持MVCC(多版本并發控制), 而MyISAM不支持。
4)從MySQL5.5.5以后,InnoDB是默認引擎。
5)MyISAM支持全文類型索引,而InnoDB不支持全文索引。
6)InnoDB中不保存表的總行數,select count(*) from table時,InnoDB需要掃描整個表計算有多少行,但MyISAM只需簡單讀出保存好的總行數即可。注:當count(*)語句包含where條件時MyISAM也需掃描整個表。
7)對于自增長的字段,InnoDB中必須包含只有該字段的索引,但是在MyISAM表中可以和其他字段一起建立聯合索引。
8)清空整個表時,InnoDB是一行一行的刪除,效率非常慢。MyISAM則會重建表。MyisAM使用delete語句刪除后并不會立刻清理磁盤空間,需要定時清理,命令:
OPTIMIZE table dept;
9)InnoDB支持行鎖(某些情況下還是鎖整表,如?update table set a=1 where user like ‘%lee%’)
10)存儲結構:
? ? ? ? MyISAM:每個MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型。.frm文件存儲表定義。數據文件的擴展名為.MYD (MYData)。索引文件的擴展名是.MYI (MYIndex)。
? ? ? ? InnoDB:所有的表都保存在同一個數據文件中(也可能是多個文件,或者是獨立的表空間文件),InnoDB表的大小只受限于操作系統文件的大小,一般為2GB11)表主鍵:
? ? ? ? ?MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保存行的地址。
? ? ? ? ?InnoDB:如果沒有設定主鍵或者非空唯一索引,就會自動生成一個字節的主鍵(用戶不可見),數據是主索引的一部分,附加索引保存的是主索引的值。12)可移植性、備份及恢復:
? ? ? ? MyISAM:數據是以文件的形式存儲,所以在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操作。
? ? ? ?InnoDB:免費的方案可以是拷貝數據文件、備份 binlog,或者用 mysqldump,在數據量達到幾十G的時候就相對痛苦了應用場景:
- MyISAM不支持事務處理等高級功能,但它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那么MyISAM是更好的選擇。
- InnoDB用于需要事務處理的應用程序,包括ACID事務支持。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶并發操作的性能。一般都選用InnoDB
Mysql中有哪幾種鎖?
表鎖:select * from tb for update;(鎖:for update)
行鎖:select id ,name from tb where id=2 for update;(鎖:for update)
- MyISAM支持表鎖,InnoDB支持表鎖和行鎖,默認為行鎖
- 表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖沖突的概率最高,并發量最低
- 行級鎖:開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖沖突的概率小,并發度最高
3、簡述數據三大范式?
據庫的三大特性:
'實體':表
'屬性':表中的數據(字段)
'關系':表與表之間的關系
----------------------------------------------------
數據庫設計三大范式:
第一范式(1NF):字段具有原子性,不可再分。(所有關系型數據庫系統都滿足第一范式數據庫表中的字段都是單一屬性的,不可再分)
第二范式(2NF)是在第一范式(1NF)的基礎上建立起來的,即滿足第二范式(2NF)必須先滿足第一范式(1NF)。要求數據庫表中的每個實例或行必須可以被惟一地區分。通常需要為表加上一個列,以存儲各個實例的惟一標識。這個惟一屬性列被稱為主關鍵字或主鍵。
滿足第三范式(3NF)必須先滿足第二范式(2NF)。簡而言之,第三范式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。
所以第三范式具有如下特征:
?1. 每一列只有一個值
?2. 每一行都能區分。
?3. 每一個表都不包含其他表已經包含的非主關鍵字信息。
6、簡述數據庫設計中一對多和多對多的應用場景?
一對一關系示例:
一個學生對應一個學生檔案材料,或者每個人都有唯一的身份證編號。
一對多關系示例:(下拉單選)
一個學生只屬于一個班,但是一個班級有多名學生。
多對多關系示例:(下拉多選)
一個學生可以選擇多門課,一門課也有多名學生。
7、如何基于數據庫實現商城商品計數器?
參考:點擊查看
8、常見SQL(必備)
詳見:點擊查看
9、簡述觸發器、函數、視圖、存儲過程?
觸發器:
? ? 對數據庫某個表進行【增、刪、改】前后,自定義的一些SQL操作
函數:
? ? 在SQL語句中使用的函數 #例如:select sleep(2)
? ? 聚合函數:max、sam、min、avg
? ? 時間格式化:date_format
? ? 字符串拼接:concat
? ? 自定制函數:(觸發函數通過 select)
視圖:
? ? 對某些表進行SQL查詢,將結果實時顯示出來(是虛擬表),只能查詢不能更新
存儲過程:
? ? 將提前定義好的SQL語句保存到數據庫中并命名;以后在代碼中調用時直接通過名稱即可
? ? 參數類型:in、out、inout
13、MySQL常見的函數?
'當前時間'
? ? select now();
'時間格式化'
? ? select DATE_FORMAT(NOW(), '%Y(年)-%m(月)-%d(日) %H(時):%i(分):%s(秒)')
'日期加減'
? ? select DATE_ADD(DATE, INTERVAL expr unit)
? ? select DATE_ADD(NOW(), INTERVAL 1 DAY) #當前日期加一天
? ? \expr:正數(加)、負數(減)
? ? \unit:支持毫秒microsecond、秒second、小時hour、天day、周week、年year
'類型轉換'
? ? cast( expr AS TYPE)?
? ? select CAST(123 AS CHAR)
'字符串拼接'
? ? concat(str1,str2,……)
? ? select concat('hello','2','world') --> hellow2world
'聚合函數'
? ? avg() #平均值
? ? count() #返回指定列/行的個數
? ? min() #最小值
? ? max() #最大值
? ? sum() #求和
? ? group_concat() #返回屬于一組的列值,連接組合而成的結果
'數學函數'
? ? abs() #絕對值
? ? bin() #二進制
? ? rand() #隨機數
15、如何開啟慢日志查詢?
可以通過修改配置文件開啟
slow_query_log=ON ? ? ? # 是否開啟慢日志記錄
long_query_time=2 ? ? ? # 時間限制,超過此時間,則記錄
slow_query_log_file=/usr/slow.log ?# 日志文件
long_queries_not_using_indexes=ON ?# 是否記錄使用索引的搜索
16、數據庫導入導出命令(結構+數據)?
# 導出:
? ? mysqldump --no-defaults -uroot -p 數據庫名字 > 導出路徑
? ? '--no-defaults':解決“unknown option --no-beep”報錯
# 導入:
? ? 1、mysqldump -uroot -p 數據庫名稱 < 路徑
? ? 2、進入數據庫; source + 要導入數據庫文件路徑
數據庫優化方案?
詳細可參考:https://blog.csdn.net/fenglepeng/article/details/103400418
1、創建數據表時把固定長度的放在前面
2、將固定數據放入內存:choice字段(django中用到,1,2,3對應相應內容)
3、char不可變,varchar可變
4、聯合索引遵循最左前綴(從最左側開始檢索)
5、避免使用 select *
6、讀寫分離:
? ? #利用數據庫的主從分離:主,用于刪除、修改、更新;從,用于查
? ? #實現:兩臺服務器同步數據
? ? \原生SQL:select * from db.tb
? ? \ORM:model.User.object.all().using('default')
? ? \路由:db router
7、分庫
? ? # 當數據庫中的表太多,將某些表分到不同數據庫,例如:1W張表時
? ? # 代價:連表查詢跨數據庫,代碼變多
8、分表
? ? # 水平分表:將某些列拆分到另一張表,例如:博客+博客詳情
? ? # 垂直分表:將某些歷史信息,分到另外一張表中,例如:支付寶賬單
9、加緩存
? ? # 利用redis、memcache(常用數據放到緩存里,提高取數據速度)
? ? # 緩存不夠可能會造成雪崩現象
10、如果只想獲取一條數據
? ? select * from tb where name = 'zgc' limit 1;
19、簡述MySQL的執行計劃?
詳細可參考:https://blog.csdn.net/fenglepeng/article/details/103392319
# explain + SQL語句
# SQL在數據庫中執行時的表現情況,通常用于SQL性能分析,優化等場景。
?'explain select * from rbac_userinfo where id=1;'
24、簡述數據庫讀寫分離?
# 利用數據庫的主從分離:主,用于刪除、修改、更新;從,用于查
#實現:兩臺服務器同步數據(減輕服務器的壓力)
? ? ? ?原生SQL: select * from db.tb
? ? ? ?ORM:model.User.object.all().using('default')
? ? ? ?路由:db router
25、簡述數據庫分庫分表?(水平、垂直)
# 1、分庫
? ? 當數據庫中的表太多,將某些表分到不同數據庫,例如:1W張表時
? ? 代價:連表查詢跨數據庫,代碼變多
# 2、分表
? ? 水平分表:將某些列拆分到另一張表,例如:博客+博客詳情
? ? 垂直分表:將某些歷史信息,分到另外一張表中,例如:支付寶賬單
char和varchar、Varbinary 存儲字符的區別?
char使用固定長度的空間進行存儲,char(4)存儲4個字符,根據編碼方式的不同占用不同的字節,gbk編碼方式,不論是中文還是英文,每個字符占用2個字節的空間,utf8編碼方式,每個字符占用3個字節的空間。
如果需要存儲的字符串的長度跟所有值的平均長度相差不大(定值),適合用char。
對于經常改變的值,char優于varchar,原因是固定長度的行不容易產生碎片。對于很短的列,char優于varchar,原因是varchar需要額外一個或兩個字節存儲字符串的長度。
varchar保存可變長度的字符串,使用額外的一個或兩個字節存儲字符串長度,varchar(10),除了需要存儲10個字符,還需要1個字節存儲長度信息(10),超過255的長度需要2個字節來存儲
binary保存二進制字符串,它保存的是字節而不是字符,沒有字符集限制
binary(8)可以保存8個字符,每個字符占1個字節,共占8個字節(01串)
delete、drop、truncate區別
- truncate?和?delete只刪除數據,不刪除表結構?,drop刪除表結構,并且釋放所占的空間。
- 刪除數據的速度,drop> truncate > delete
- delete屬于DML語言,需要事務管理,commit之后才能生效。drop和truncate屬于DDL語言,操作立刻生效,不可回滾。
- 使用場合:
- 當你不再需要該表時, 用?drop;
- 當你仍要保留該表,但要刪除所有記錄時, 用?truncate;
- 當你要刪除部分記錄時(always with a where clause),?用?delete.
Float、Decimal 存儲金額的區別?
浮點數計算都不準(只要不是2的整數倍都會有問題)。decimal存儲其實是string類型存儲。
Datetime、Timestamp 存儲時間的區別?
對于TIMESTAMP,它把客戶端插入的時間從當前時區轉化為UTC(世界標準時間)進行存儲。查詢時,將其又轉化為客戶端當前時區進行返回。對于跨時區的業務,TIMESTAMP更為合適。
而對于DATETIME,不做任何改變,基本上是原樣輸入和輸出。
HAVING 子句 和 WHERE的異同點?
語法上:where 用表中列名,having用select結果別名
影響結果范圍:where從表讀出數據的行數,having返回客戶端的行數
索引:where 可以使用索引,having不能使用索引,只能在臨時結果集操作
where后面不能使用聚集函數,having是專門使用聚集函數的。
mysql 備份
mysql的復制原理以及流程。
Mysql內建的復制功能是構建大型,高性能應用程序的基礎。將Mysql的數據分布到多個系統上去,這種分布的機制,是通過將Mysql的某一臺主機的數據復制到其它主機(slaves)上,并重新執行一遍來實現的.
復制過程中一個服務器充當主服務器,而一個或多個其它服務器充當從服務器。主服務器將更新寫入二進制日志文件,并維護文件的一個索引以跟蹤日志循環。這些日志可以記錄發送到從服務器的更新。 當一個從服務器連接主服務器時,它通知主服務器在日志中讀取的最后一次成功更新的位置。從服務器接收從那時起發生的任何更新,然后封鎖并等待主服務器通知新的更新。 過程如下
主服務器把更新記錄到二進制日志文件中。
從服務器把主服務器的二進制日志拷貝到自己的中繼日志(replay log)中。
從服務器重做中繼日志中的時間,把更新應用到自己的數據庫上。
mysql支持的復制類型?
基于語句的復制: 在主服務器上執行的SQL語句,在從服務器上執行同樣的語句。MySQL默認采用基于語句的復制,效率比較高。 一旦發現沒法精確復制時,會自動選著基于行的復制。
基于行的復制:把改變的內容復制過去,而不是把命令在從服務器上執行一遍. 從mysql5.0開始支持
混合類型的復制: 默認采用基于語句的復制,一旦發現基于語句的無法精確的復制時,就會采用基于行的復制。
MySQL的binlog有有幾種錄入格式?分別有什么區別?
有三種格式,statement,row和mixed.
statement模式下,記錄單元為語句.即每一個sql造成的影響會記錄.由于sql的執行是有上下文的,因此在保存的時候需要保存相關的信息,同時還有一些使用了函數之類的語句無法被記錄復制.
row級別下,記錄單元為每一行的改動,基本是可以全部記下來但是由于很多操作,會導致大量行的改動(比如alter table),因此這種模式的文件保存的信息太多,日志量太大.
mixed. 一種折中的方案,普通操作使用statement記錄,當無法使用statement的時候使用row.
MySQL中空值和NULL的區別?
- 空值(”)是不占用空間的,判斷空字符用 = ” 或者 <> ” 來進行處理。
- NULL值是未知的,且占用空間,不走索引;判斷 NULL 用 IS NULL 或者 is not null ,SQL 語句函數中可以使用 ifnull ()函數來進行處理。
- 無法比較 NULL 和 0;它們是不等價的。
- 無法使用比較運算符來測試 NULL 值,比如 =, <, 或者 <>。
NULL
?值可以使用?<=>
?符號進行比較,該符號與等號作用相似,但對NULL
有意義。- 進行 count ()統計某列的記錄數的時候,如果采用的 NULL 值,會別系統自動忽略掉,但是空值是統計到其中。