創建數據庫luowei
mysql> CREATE DATABASE luowei;
使用數據庫
mysql> use luowei
創建表study
mysql> CREATE TABLE study ( ID bigint(20) NOT NULL AUTO_INCREMENT UNIQUE, Name varchar(255) NOT NULL, Age int(10),Gender enum('F','M') DEFAULT 'M');
查詢表study;
mysql> SELECT * FROM study;
查看表的結構:
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
+--------+---------------+------+-----+---------+----------------+
插入數據;
mysql> INSERT INTO study (Name) VALUE ('luowei'); //單個插入
mysql> INSERT INTO study (Name) VALUE ('Qi'),('Ro'),('RQ'); //批量插入
mysql> INSERT INTO study SET Name='Hua'; //使用SET插入
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | M |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | M |
| 5 | Hua | NULL | M |
+----+--------+------+--------+
5 rows in set (0.00 sec)
這是插入數據後的一個簡單的表的內容
修改表的數據
mysql> UPDATE study SET Gender='F' WHERE ID=2; //把ID=2的Gender改為F
mysql> UPDATE study SET Gender='F' WHERE ID IN (4,5);//批量處理
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | F |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | F |
| 5 | Hua | NULL | F |
+----+--------+------+--------+
刪除表中的數據
mysql> DELETE FROM study WHERE ID=5;//刪除指定的行
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | F |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | F |
+----+--------+------+--------+
但是這個時候如果我們在再次插入的話ID號會從原來刪除的編號增加
mysql> SELECT LAST_INSERT_ID();//顯示上次插入的是第幾個
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 5 |
+------------------+
mysql> INSERT INTO study (Name) VALUE ('aQ');
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | F |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | F |
| 6 | aQ | NULL | M |
+----+--------+------+--------+
看到了吧,不是依次增長的,而是有間隔,現在我們在刪除了ID為6的行,然後插入設置他的ID為5,接著再自動插入;
mysql> DELETE FROM study WHERE ID=6;
mysql> INSERT INTO study SET ID=5,Name='pk';
mysql> INSERT INTO study (Name) VALUE ('jk');
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | F |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | F |
| 5 | pk | NULL | M |
| 7 | jk | NULL | M |
+----+--------+------+--------+
可以看出還是不會按照我們的意思讓他接著自動增長,這個時候我們可以通過設置,讓他重新按照我們設置的為起點自動增長
mysql> DELETE FROM study WHERE ID=7;
mysql> ALTER TABLE study AUTO_INCREMENT=5;//設置自動增長的起點
mysql> INSERT INTO study (Name) VALUE ('jk');
mysql> INSERT INTO study (Name) VALUE ('OL');
mysql> SELECT * FROM study;
+----+--------+------+--------+
| ID | Name | Age | Gender |
+----+--------+------+--------+
| 1 | luowei | NULL | M |
| 2 | Qi | NULL | F |
| 3 | Ro | NULL | M |
| 4 | RQ | NULL | F |
| 5 | pk | NULL | M |
| 6 | jk | NULL | M |
| 7 | OL | NULL | M |
+----+--------+------+--------+
又OK了,我估計QQ在設置QQ號的時候也是通過這種方式,保留小於5位的QQ號,所有大家用的都是7位以上的(題外話,呵呵)。
修改表結構
如果想插入一個新的字段,可以使用ALTER來修改
mysql> DESC study;//原本表的結構
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
+--------+---------------+------+-----+---------+----------------+
mysql> ALTER TABLE study ADD Work INT ;
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
| Work | int(11) | YES | | NULL | |
+--------+---------------+------+-----+---------+----------------+
默認插入最後一行,如果想插入指定的行,可以使用AFTER,FIRST等參數
mysql> ALTER TABLE study ADD Master VARCHAR(30) AFTER Gender;
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
| Master | varchar(30) | YES | | NULL | |
| Work | int(11) | YES | | NULL | |
+--------+---------------+------+-----+---------+----------------+
這就把新插入的字段放在了Gender的後面了
如果我們想把原來的表中字段的名字改一下,比如我想把Work改成work
mysql> ALTER TABLE study CHANGE Work work INT;//修改表中的字段
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
| Master | varchar(30) | YES | | NULL | |
| work | int(11) | YES | | NULL | |
+--------+---------------+------+-----+---------+----------------+
可以實現效果
當讓還可以通過使用MODIFY來試下對表中字段的屬性進行設置
mysql> ALTER TABLE study MODIFY work VARCHAR(30) NOT NULL ;
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
| Master | varchar(30) | YES | | NULL | |
| work | varchar(30) | NO | | NULL | |
+--------+---------------+------+-----+---------+----------------+
但是如果你表中原本work中沒有字段的話,會有warning,所以在你做的時候可以先添加數據,然後在修改。
隨著發展,我發現後面的work這個字段沒用了,想刪除study表中的這個屬性
mysql> ALTER TABLE study DROP work;
mysql> DESC study;
+--------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| Name | varchar(255) | NO | | NULL | |
| Age | int(10) | YES | | NULL | |
| Gender | enum('F','M') | YES | | M | |
| Master | varchar(30) | YES | | NULL | |
+--------+---------------+------+-----+---------+----------------+
當然如果我們表中有索引(目前),也可以使用DROP刪除索引
mysql> SHOW INDEX FROM study;//查看表的索引
mysql> ALTER TABLE study ADD INDEX index_name(Name);//添加索引
也可以私用KEY(mysql> ALTER TABLE study ADD KEY index_name(Name);)
mysql> SHOW INDEX FROM study;
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| study | 0 | ID | 1 | ID | A | 7 | NULL | NULL | | BTREE | |
| study | 1 | index_name | 1 | Name | A | NULL | NULL | NULL | | BTREE | |
+-------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
mysql> ALTER TABLE study DROP INDEX index_name;//刪除索引
現在我覺得表明有點長,想換一個短的來方便下面的實驗,當然在實際的過程中,我們應該見名知意
mysql> ALTER TABLE study RENAME TO st;//把表名從study改成st
mysql> SHOW TABLES;
+------------------+
| Tables_in_luowei |
+------------------+
| st |
+------------------+
想查看當前的數據庫可以使用一下命令
mysql> SELECT DATABASE();
mysql> SHOW TABLES;//顯示當前數據庫中的表
mysql> SELECT * FROM st;
+----+--------+------+--------+--------+
| ID | Name | Age | Gender | Master |
+----+--------+------+--------+--------+
| 1 | luowei | NULL | M | NULL |
| 2 | Qi | NULL | F | NULL |
| 3 | Ro | NULL | M | NULL |
| 4 | RQ | NULL | F | NULL |
| 5 | pk | NULL | M | NULL |
| 6 | jk | NULL | M | NULL |
| 7 | OL | NULL | M | NULL |
+----+--------+------+--------+--------+
這裡我只有一個表,現在我修改一下表中的數據,把Master的類型改為INT,並添加一些數據在裡面
mysql> ALTER TABLE st CHANGE MODIFY Master INT;
mysql> UPDATE st SET Master=1 WHERE ID=1;
mysql> UPDATE st SET Master=2 WHERE ID=2;
mysql> UPDATE st SET Master=3 WHERE ID=3;
mysql> UPDATE st SET Master=4 WHERE ID=4;
mysql> UPDATE st SET Master=7 WHERE ID=5;
mysql> UPDATE st SET Master=8 WHERE ID=6;
mysql> UPDATE st SET Master=5 WHERE ID=7;
mysql> SELECT * FROM st;
+----+--------+------+--------+--------+
| ID | Name | Age | Gender | Master |
+----+--------+------+--------+--------+
| 1 | luowei | NULL | M | 1 |
| 2 | Qi | NULL | F | 2 |
| 3 | Ro | NULL | M | 3 |
| 4 | RQ | NULL | F | 4 |
| 5 | pk | NULL | M | 7 |
| 6 | jk | NULL | M | 8 |
| 7 | OL | NULL | M | 5 |
+----+--------+------+--------+--------+
現在表的基本情況如上所示。當然我們為了方便記錄Master,使用是INT來標,其實Master是一個姓名,所以我們再建立一個新表mt,來記錄Master的對應的關系
mysql> CREATE TABLE mt(
-> id INT NOT NULL UNIQUE AUTO_INCREMENT ,
-> name VARCHAR(30) NOT NULL );
mysql> INSERT INTO mt (name) VALUE ('A');
......
自己多插入幾行,我這裡就省略了
mysql> SELECT * FROM mt;
+----+------+
| id | name |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
| 6 | F |
+----+------+
好了現在兩個表准備好了,接下來我將做一下多表之間的查詢
多表之間的查詢可以分為:
交叉查詢:笛卡爾乘積,兩表相乘;
內連接:對稱連接,就是顯示兩個表中都有的,一個表中如果沒有,就不顯示了;
外連接:非對稱連接
左外連接:LEFT JOIN ON 左表中的都顯示,右表中無的話顯示為NULL
右外連接:RIGHT JOIN ON 右表中的都顯示,左表中無的話顯示為NULL
自連接:一個表中的一列建立在同張表的另一列;
UNION:連接兩個表;
接下來分別對上面的情況進行實驗;
1.交叉查詢:
mysql> SELECT * FROM st,mt;
42 rows in set (0.00 sec)//中間的數據就省略了,這裡的結果就是兩個表的行數相乘的結果;
2.內連接:
mysql> SELECT st.Name,mt.name FROM st,mt WHERE st.Master=mt.id;
+--------+------+
| Name | name |
+--------+------+
| luowei | A |
| Qi | B |
| Ro | C |
| RQ | D |
| OL | E |
+--------+------+
3.左外連接:
mysql> SELECT st.Name,mt.name FROM st LEFT JOIN mt ON st.Master=mt.id;
+--------+------+
| Name | name |
+--------+------+
| luowei | A |
| Qi | B |
| Ro | C |
| RQ | D |
| pk | NULL |
| jk | NULL |
| OL | E |
+--------+------+
這時候我們可以看到,凡是左表中有的,都顯示了,右表中沒有的都顯示為NULL了;
4.右外連接:
mysql> SELECT st.Name,mt.name FROM st RIGHT JOIN mt ON st.Master=mt.id;
+--------+------+
| Name | name |
+--------+------+
| luowei | A |
| Qi | B |
| Ro | C |
| RQ | D |
| OL | E |
| NULL | F |
+--------+------+
5.自連接:
mysql> SELECT k1.Name,k2.Gender FROM st AS k1,st AS k2 WHERE k1.ID = k2.Master;
+--------+--------+
| Name | Gender |
+--------+--------+
| luowei | M |
| Qi | F |
| Ro | M |
| RQ | F |
| OL | M |
| pk | M |
+--------+--------+
6.UNION;
mysql> SELECT ID AS new_id,Name AS new_name FROM st UNION SELECT id AS new_id,name AS new_name FROM mt;
+--------+----------+
| new_id | new_name |
+--------+----------+
| 1 | luowei |
| 2 | Qi |
| 3 | Ro |
| 4 | RQ |
| 5 | pk |
| 6 | jk |
| 7 | OL |
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
| 5 | E |
| 6 | F |
+--------+----------+
13 rows in set (0.00 sec)這樣就把兩個表連接到了一起了。
多表操作就到此了,接下來要說的是數據庫中的視圖,子查詢,事務,同步的相關知識了;
我就以st這個表為基礎:
mysql> SELECT * FROM st;
+----+--------+------+--------+--------+
| ID | Name | Age | Gender | Master |
+----+--------+------+--------+--------+
| 1 | luowei | NULL | M | 1 |
| 2 | Qi | NULL | F | 2 |
| 3 | Ro | NULL | M | 3 |
| 4 | RQ | NULL | F | 4 |
| 5 | pk | NULL | M | 7 |
| 6 | jk | NULL | M | 8 |
| 7 | OL | NULL | M | 5 |
+----+--------+------+--------+--------+
視圖:就是建立在基表上執行查詢語句的一系列的虛表
創建視圖:
mysql> CREATE VIEW view AS SELECT ID,Name,Gender FROM st;//創建一個查詢顯示ID,Name,Gender的視圖;
mysql> SELECT * FROM view;
+----+--------+--------+
| ID | Name | Gender |
+----+--------+--------+
| 1 | luowei | M |
| 2 | Qi | F |
| 3 | Ro | M |
| 4 | RQ | F |
| 5 | pk | M |
| 6 | jk | M |
| 7 | OL | M |
+----+--------+--------+
刪除視圖可以使用
mysql> DROP VIEW view;
子查詢語句:(其實MySQL的子查詢支持的還不是很好)
mysql> SELECT * FROM view WHERE ID > 0;
我就借用剛建立的視圖進行查詢,其實這個是多此一舉的做法,呵呵,只是演示一下效果,當讓在工作中可能會遇到更多的問題的。
事務:transact
事務就是幾個Sql語句要麼都執行,要麼都不執行,這樣就防治一方執行,另一方沒執行,從而產生虛擬的假象,比如A通過銀行向B轉賬,如果這個時候A剛轉出去,B那邊的斷電了(假設,其實這樣的事出現的概率還是蠻小的,呵呵),所以等A和B見面之後,就說不清了,所以事務就是如果兩個都沒實現,就是A發送成功,B接受成功,才能算是真正的成功,所以這樣就能避免不必要的損失。
接下來介紹一下事務隔離的級別:
1.讀未提交 READ UNCOMMITED
2.讀提交 READ COMMITED
3.可重讀 REPEATABLE READ 默認
4.串行化 SERIABLIZABLE
從1-->4隔離級別依次增加,並發性依次降低
mysql> SHOW VARIABLES LIKE 'tx_isolation';//查看系統使用的默認的隔離級別
+---------------+-----------------+
| Variable_name | Value |
+---------------+-----------------+
| tx_isolation | REPEATABLE-READ |
+---------------+-----------------+
但是如果我們的數據庫使用的引擎是MyISAM的話,就不支持事務,查看數據庫使用的引擎命令如下
mysql> SHOW ENGINES;或使用SHOW TABLE STATUS LIKE 'st';或使用SHOW TABLE STATUS ;都能查看
+------------+---------+----------------------------------------------------------------+
| Engine | Support | Comment |
+------------+---------+----------------------------------------------------------------+
| MyISAM | DEFAULT | Default engine as of MySQL 3.23 with great performance |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables |
| InnoDB | YES | Supports transactions, row-level locking, and foreign keys |
| BerkeleyDB | YES | Supports transactions and page-level locking |
| BLACKHOLE | NO | /dev/null storage engine (anything you write to it disappears) |
| EXAMPLE | NO | Example storage engine |
| ARCHIVE | NO | Archive storage engine |
| CSV | NO | CSV storage engine |
| ndbcluster | NO | Clustered, fault-tolerant, memory-based tables |
| FEDERATED | NO | Federated MySQL storage engine |
| MRG_MYISAM | YES | Collection of identical MyISAM tables |
| ISAM | NO | Obsolete storage engine |
+------------+---------+----------------------------------------------------------------+
顯示為DEFAULT的是默認使用的引擎,應為這個時候數據庫不支持事務,為了演示事務的效果,我把mysql的引擎改為InnoDB ,使用如下命令:
mysql> SET SESSION storage_engine = InnoDB;
然後在這個引擎的基礎上建立一個表
mysql> CREATE TABLE tt (
-> tid INT UNIQUE NOT NULL AUTO_INCREMENT,
-> tname VARCHAR(30) NOT NULL,
-> tage INT);
插入數據如下圖所示,當然你可以自己隨便添加表中的數據
mysql> SELECT * FROM tt;
+-----+-------+------+
| tid | tname | tage |
+-----+-------+------+
| 1 | ser | NULL |
| 2 | linux | NULL |
| 3 | php | NULL |
+-----+-------+------+
查看當前表的存儲引擎
mysql> SHOW TABLE STATUS LIKE 'tt';
顯示的結果是InnoDB的引擎;
1.設置為READ UNCOMMITTED(讀未提交)的級別
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;//修改隔離級別為READ UNCONMMITED顯示為REPEATABLE-READ
mysql> SHOW VARIABLES LIKE 'tx_isolation';
+---------------+------------------+
| Variable_name | Value |
+---------------+------------------+
| tx_isolation | READ-UNCOMMITTED |
+---------------+------------------+
這個級別下,如果兩個事務同時進行,任何一方的改變,對方都能看到,因為我們在設置的時候采用的是SESSION,會話的模式,所以兩個終端都要進行READ UNCOMMITTED設置
所以這個的設置的並發性最好,但是受到的影響卻是最大的
2.設置為READ COMMITED(讀提交)級別
這個級別下,當其中的任意一個事務提交了,其他處於事務狀態的就能同步到信息,如下圖是沒有提交之前的圖,這個時候還不能看到
如果B的事務提交了,再來看看這個結果,如下圖所示:
盡管A沒有提交,但是也能看到信息了
3.設置為REPEATABLE READ(可重讀)級別
如果設置為這個級別的話,兩個同時進行的事務,相互不受影響,只用當兩個事務都提交了才能看到所有變化的信息,否則,各自只能看到自己完成的
我現在打開兩個終端A、B,同時進入事務
mysql> START TRANSACTION;//A進入事務狀態
mysql> START TRANSACTION;//B進入事務狀態
然後我在B事務狀態下向表進行插入一行數據,然後在兩個表中都查看,結果發現數據不一樣,如下圖所示:
如果我現在把B的事務提交了,再在A、B上查看,發現只有B上的有新插入的一行,而A任然沒有,如圖所示:
如果我現在把A的也提交了,在查看的話,兩個就會出現數據同步了,如圖所示:
這就是REPEATABLE READ級別的效果,就是兩個事務操作的時候相互不干擾,只有當兩個事務都提交了,數據才會同步。
4.設置為SERIABLIZABLE級別
這個時候只有當前一個事務執行完成並提交了,下一個事務才開始,做了更加嚴格的限制,所以一般不做這樣的級別限制
同步:(clock)
通過鎖機制來解決同步問題
鎖:
共享鎖(讀鎖):
獨占鎖(寫鎖):
寫鎖的優先級高於讀鎖
鎖級別:
表鎖,行鎖,頁鎖(內存空間)
鎖的實現:
服務器級別的;只能實現表鎖
存儲引擎級別的:可以實現行鎖
>LOCK TABLES tab_name READ;加鎖
>UNLOCK TABLES;釋放鎖
(注意:如果在InnoDB中,定義時候並不生效,只有真正的事務開始,
定義的鎖才生效)
降低粒度,可以更好的支持並發性,這樣鎖的顆粒就越小,類似行鎖,鎖的
范圍小一些。
MYSQL的用戶管理:
創建用戶
CREATE USER username@host
刪除用戶
DROP USER username@host
授權
GRANT PRIV_LIST ON db.table TO username@host [IDENTIFIED BY 'redhat'];
收回權限
REVOKE priv_list ON db.table FROM username@host;
WITH GRANT OPTION 同時把授權也一並授權給他
設置其使用的資源:
WITH MAX_QUERIES_PER_HOUT N;每個小時只能做N次查詢
WITH MAX_UPDATES_PER_HOUT N每個小時只能做N次更新
WITH MAX_CONNECTIONS_PER_HOUT N 每個小時只能做N次連接
WITH MAX_USER_CONNECTIONS N 每個用戶同時最大連接數
FLUSH USER_RESOURCES;
GRANT SELECT(name) ON db.table TO uername@host;字段級別的權限
執行存儲過程的權限
GRANT EXECUTE ON XXXX TO username@host
忘記MySQL的密碼:
方法1.重裝數據庫
方法2.
vim /etc/init.d/mysqld
先停止MySQL服務
#service mysqld stop
找到mysqld的二進制文件的位置,我這裡就在/user/local/mysql/下
#/user/local/mysql/bin/mysqld_safe --skip-grant-tables --skip-networking & 後台運行安全模式
然後連接數據庫
#mysql
>use mysql
>UPDATE user SET Password=PASSWORD('redhat') WHERE User='root' AND Host='localhost';
>UPDATE user SET Password=PASSWORD('redhat') WHERE User='root' AND Host='127.0.0.1';
#killall mysqqld
#service mysqld start
#mysql -uroot -p 登錄
作者 “IT夢-齊-分享”