mysql概念
约束 constraint
- 約束:明確有效數據範圍;定義數據時要有約束
- 域約束:數據類型約束
- 外鍵約束:引用完整性約束;是降低數據冗餘的手段;一個表中填的值一定要保證在另外一個表中有相同的值才允許使用。級連表示如果這張表被其他表依賴,如果刪除了這張表,被依賴的表也會被刪。一般不用。與外鍵約束有關。
- 主鍵約束:某字段能惟一標識此字段所屬的實體,並且不允許為空,不能有相同值。可當主鍵的鍵叫候選鍵。一個表只能有一個主鍵
- 唯一性約束:每一行的某字段都不允許出現相同值,可以為空,一張表可以有多個唯一鍵。
- 檢查性約束:age:int定義符合現實的邏輯。
mysql的rpm包
- mysql-client :提供客戶端及組件
- mysql-debuginfo:可幫助調試mysql,一般開發人員用
- my-devel:開發組件,開發用的頭文件與庫文件
- mysql-embedded:嵌入式服務專用
- mysql-ndb-management :Cluster server上專用的組件,平常不用
- mysql-server
- mysql-shared:共享庫
- mysql-shared-compat:為老版本的兼容庫,是shared的補充
- mysql-test:測試用組件
- mysql-version.platform.src.rpm:源碼格式的rpm包
安裝後的目錄結構
- bin:二進制程序,命令
- data:數據目錄
- include:頭文件
- lib:庫文件
- man:手冊
- mysql-test:測試組件
- scripts:初始化腳本
- share:語言版本
- sql-bench:基准測試
- support-files:腳本、樣例、等
linux mysql啟動時查找的配置文件
1 | 每次啓動,mysql都要讀取下面文件 |
windows mysql啟動時查找的配置文件
1 | 1. %WINDIR%\my.ini, %WINDIR%\my.cnf |
請求過程
當用戶需要連到數據庫上來完成某種操作時,由連接器負責接收用戶請求,並將請求轉發給線程管理器,線程管理器給它創建一個線程,線程管理器將線程權限轉給用戶模塊,用戶模塊來驗證用戶是否有訪問權限,如果沒有就終止,有就建立連接。之後用戶發起命令,由命令分發模块來完成用戶請求內容是否從緩存中直接返回,是否記錄日志,如果緩存中沒有的話, 可能就要將命令語句轉給解析器分析生成執行树,並交由底層的對應模塊處理,如果是SELECT語句就交給優化器,來生成更優的執行過程,如果用戶發起與數據定義相關的命令都要交給表定義模塊,如INSERT,DELECT等,如果用戶要維護一張表,就交給表維護模塊來完成,用戶每發起一次命令語句,狀態信息都要更新,最終,不論用戶是哪種請求都要判斷用戶是否有對應的訪問權限,這由訪問控制模塊來完成,如果有,就由表管理器負責後續的動作,如讀取表結構、修改表結構、施加表鎖,最終由存儲引擎來負責到對應文件中去找對應的數據。存儲引擎是真正與磁盤打交道的接口。這就是mysql的微觀結構
mysql基礎架構
面對用戶的一端是連接管理器,接收請求並建立連接後的下一層是查詢緩存和分析器,如果查詢緩存中有結果就直接返回給用戶,查詢緩存只與讀操作有關,與寫無關,且只與讀操作的查詢操作有關,如果緩存中沒有結果,就由分析器來分析,分析的結果如果發現緩存中有結果還會從緩存中返回結果,如果沒有結果就交給優化器完成優化,而後就交給存儲引擎,或交給執行引擎再交給存儲引擎完成操作。這就是mysql的基礎架構。連接管理器就是監聽在某個套接字上接收用戶請求,接收後創建一個線程予以響應,因為創建線程很消耗資源,也為了加速線程的創建,所以有了重用線程的概念,用戶退出後線程不被銷毀,而是放到空閒線程池中,有新的用戶請求時直接從空閒線程中拿一個給用戶響應,創建連接後會驗證用戶的連入權限,連入的所有用戶的操作都在它自身的線程地址空間內完成,因CPU有限,每個用戶發起的操作都在CPU上輪流進行,如果有一個非常慢的話會使其他用戶請求非常慢。在遠程連接mysql服務器時數據通過tcp/ip協議傳輸,是明文的,如果是機密的數據,會話管理器(連接管理器)還要進行加密
當我們發起查詢請求後mysql服務器會負責解析每一個查詢,並在mysql進程內部創建一個解析樹,它會去解析每一個請求,並為這個請求創建一個解析樹,解析執行過程並優化,最後計算出最優執行路徑,這就是解析器和優化器的作用。優化器的優化是自我判定的,與實際場景可能有出入,所以結果未必是最佳的。作為用戶可以給優化器提示,在執行語句中,這就避免優化器再去查找。優化器在優化中不會考慮存儲引擎的不同,每一個查詢執行結束之後,如果結果是決定性的,mysql會將結果緩存下來,但視查詢結果大小,不是所有結果都可以緩存的,一定是小於某個上限的才緩存。
緩存(一段內存空間)中的內容被分成了三個區域,每個區域中有一個叫作緩存槽的東西,每個查詢結果都會佔用這個槽的,為了便於管理,槽是有下限的,因為每個結果都要佔用一個槽,如果結詢結果比槽小的多,還要進行緩存,這會浪費槽,如果不浪費,自動去減小緩存空間,也會使緩存中產生大量的碎片,這也會影響執行效率。為了發揮緩存的效能提高效率,對緩存要進行優化,要有限定。非確定性結果,每次結果都不同,如查看時間(SELECT CURRENT_TIME())一般不緩存。兩個語句一樣也不一定就能緩存,比如兩個查詢的用戶權限不同,有一方沒有查詢權限,就不能緩存。沒有緩存就由解析樹處理,如果有緩存就要查在緩存中是否命中,這會使每條語句都去找一次緩存,成了額外開銷,如此要計算益處與開銷的平衡
讀寫操作同時請求同一張表,任何時候(不只mysql)有兩個用戶同時讀寫同一個文件的數據時都會有並發控制的問題
並發控制是為了提高性能,可以使兩個並發的操作不會互相影響。不能使用串行的方法,一個用戶操作完下個用戶再操作的機制。很多服務器都引入了多版本並發控制的機制,叫作MVCC,每個用戶操作的都是一個數據的副本或快照,最後再完成快照合並,快照會有一個時間值,用來判定快照的先後。時間快照是數據庫必備的功能,要實現時間並發控制就要有鎖功能,多版本並發控制是用其他功能實現的
客戶端命令:mysql、mysqladmin、mysqldump、mysqllimport、mysqlcheck
服務器:mysqld、mysqld_safe、mysqld_multi(不同端口的mysql3306、3307、3308運行在一臺服務器上,相當於多臺服務器)
數據如何存儲到磁盤
磁盤按塊加載數據到內存,如果數據只佔了塊的一部分,也要加載整個塊。多個磁盤塊可組成一個數據塊。由存儲引擎管理。一般使用定長表結構,而不用變長,這樣可以使存取速度加快。因爲塊中的行會被刪除,就空出了空間,所以要做碎片整理,碎片會使裝載速度變慢,爲了管理這樣的數據,每個塊要有塊頭,塊頭裏要有行的信息,有多少空閒行等。這個塊不一定都是磁盤塊,可能是多個磁盤塊組成的數據塊,數據塊由存儲引擎來管理,只用磁盤塊也可以。定長的表的執行速度更快。
文件中記錄組織
- 堆文件組織:一條記錄可以放在文件中的任何地方,維護簡便,管理不便
- 順序文件組織:根據“搜索碼”的值順序存放
- 散列文件組織:分成N個塊,叫桶,將某行的不同列進行hash運算,結果相同的放在一起。hash索引
程序語言連接數據的方式有兩種
- 動態SQL:通過函數或方法與數據庫服務建立連接,然後通過協議將查詢語句直接送到服務器端;簡單的方式屬於動態SQL
- 嵌入式SQL:用程序開發語言的格式寫的,通過API直接連到服務器上,連接之前要先編譯
语句中的错误提示
1 | :语句未结束,继续輸入 |
補全
要把數據庫中的表都載入內存中才能補全
名稱補全:mysql連接時用-A或–no-auto-rehash或–disable-auto-rehash來禁用補全功能;默認是有此功能的,或在mysql中用rehash或#命令就可以名稱補全了,但是是對新建命令的補全。
mysql不能啟動問題的原因
啟動時會在datadir =/mydata/data 指定的路徑下生成一個hostname.err的錯誤日志,mysql啟動後的錯誤信息都在此日志中,如果啟動錯誤還沒有錯誤日志,應該就是數據目錄指錯了。修改配置文件定義datadir =即可。测试中因为用的是mariadb,没有在目录中找到hostname.err日志,只有/var/log中的mariadb的日志,且只有一个mariadb.log
- 此前的服務未關閉套接字被佔用,用killall mysqld就可以了
- 數據初始化失敗
- 數據目錄位置錯誤
- 數據目錄權限問題
如果解決不了可重新初始化數據庫試一下
數據類型
數值型,不需要指定長度
精確數值
int:整型(TINYINT微整型1字節、SMALLINT小整型2、MEDIUMINT中整型3、INT整型4、BIGINT大整型8)
DECIMAL:精確定點數
近似數值
- FLOAT:單精度浮點型4
- DOUBLE:雙精度浮點型8
- real:實數
- NUMERIC:定點數值
- DECIMAL:定點數值
// 數值後加數字表示顯示幾位數字
字符型,一定要指定長度
定長:CHAR(#)(不區分大小寫),BINARY(區分)
變長:VARCHAR(#)(不區分大小寫),VARBINARY(區分)
text(不區分大小寫)
BLOB:二進制大對象(區分)
ENUM:枚舉(在給定的選項中選)
SET:集合(1-64個字符串,一組數值的組合值)
// CHAR最多存儲255個字符,VARCHAR最多存儲65535個字符,每個VARCHAR存儲時會多佔一個字節,因為要有一個結束符,VARCHAR在255個字符內只需要一個結束符,超出255就需要兩個結束符。text上不能索引整個字段,CHAR上可以
字符串修飾屬性
- NOT NULL:不能為空
- NULL:可為空(默認)
- DEFAULT:給一個默認值
- CHARACTER SET:字符集
- COLLATION:排序規則
二進制大對象,區分大小寫,因爲按字節排序
- TINYBLOB 255
- MEDIUMBLOB 16M
- LONGBLOB 4G
- BLOB 64K
- BINARY 255
- VARBINARY 65535
// 大對象存儲在一個單獨的位置,表上只是一個指針,故無法在表上建索引
日期時間型
- date:日期
- time:時間
- datetime:日期時間
- timestamp:時間戳
- YEAR:年
數據類型的作用
- 存入值的類型;
- 使用空間大小;
- 定長還是變長的;
- mysql如何對其進行比較和排序;
- 是否可以創建索引
// 域屬性修飾符就是定義域限制的
- 只要在一個域上定義了數據類型,它能作出以下限定
- 它能表示哪個种類的數據
- 定義最大最小值,定義空間
- 確定是變長還是定長的
- mysql如何比較排序字符,是否区分大小寫
- 這樣的類型是否能夠創建索引,是否能夠索引
查看表结构文件
1 | ls /var/lib/mysql |
存储引擎
1 | SHOW ENGINES; |