pymsql是Python中操做MySQL的模塊,其使用方法和py2的MySQLdb幾乎相同。python
pip install pymysql
import pymysql # 鏈接數據庫 xiong conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='xiong') #更改獲取數據結果的數據類型,默認是元組,能夠改成字典等:conn.cursor(cursor=pymysql.cursors.DictCursor) cursor = conn.cursor() # cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # sql = """CREATE TABLE new_EMPLOYEE ( # FIRST_NAME CHAR(20) NOT NULL, # LAST_NAME CHAR(20), # AGE INT, # SEX CHAR(1), # INCOME FLOAT )""" # 建立表 row_affected = cursor.execute("create table t1(id INT ,name VARCHAR(20))") # 向表t1中插入數據 row_affected=cursor.execute("INSERT INTO t1(id,name) values (1,'alvin'),(2,'xialv'),(3,'xiong')") # 更改數據 cursor.execute("update t1 set name = 'silv2' where id=2") cursor.execute("INSERT INTO t1(id,name) values (7,'zhou'),(8,'zhang'),(9,'fan')") #查詢數據 row_affected=cursor.execute("select * from t1") print(row_affected) #3 --共有3行數據 print(cursor.fetchone()) #第一條 print(cursor.fetchone()) #第二條 print(cursor.fetchmany(3)) #第三、四、5條 #scroll 移動光標 cursor.execute("select * from t1") print(cursor.fetchall()) #光標到最後一個位置了 # 相對絕對位置移動,移動到第2位 cursor.scroll(3 , mode='absolute') print(cursor.fetchmany(3)) print(cursor.fetchall()) # # 相對當前位置移動,負數 向上移動,正數向下移動 cursor.scroll(-1,mode='relative') print(cursor.fetchone()) # 刪除數據 cursor.execute("delete from t1 where id=2") cursor.execute("select * from t1") print(cursor.fetchall()) # 修改表中數據 cursor.execute("UPDATE t1 set name = 'xxx' WHERE id = 3") cursor.execute("select * from t1") print(cursor.fetchall()) conn.commit() cursor.close() conn.close()
事務指邏輯上的一組操做,組成這組操做的各個單元,要不所有成功,要不所有不成功。mysql
數據庫開啓事務命令 sql
-- start transaction 開啓事務 -- Rollback 回滾事務,即撤銷指定的sql語句(只能回退insert delete update語句),回滾到上一次commit的位置 -- Commit 提交事務,提交未存儲的事務 -- -- savepoint 保留點 ,事務處理中設置的臨時佔位符 你能夠對它發佈回退(與整個事務回退不一樣)
轉帳實例:數據庫
UPDATE account set balance=balance-5000 WHERE name=」yuan」;
UPDATE account set balance=balance+5000 WHERE name=」xialv」;
create table test2(id int PRIMARY KEY auto_increment,name VARCHAR(20)) engine=innodb; INSERT INTO test2(name) VALUE ("alvin"), ("yuan"), ("xialv"); start transaction; insert into test2 (name)values('silv'); select * from test2; commit; -- 保留點 start transaction; insert into test2 (name)values('wu'); savepoint insert_wu; select * from test2; delete from test2 where id=4; savepoint delete1; select * from test2; delete from test2 where id=1; savepoint delete2; select * from test2; rollback to delete1; select * from test2; savepoint
start transaction ; select * from money; insert into money (name,salary) values ("wu",8000); savepoint insert_wu; select * from money; insert into money (name,salary) values ("chen",7000); savepoint insert_chen; select * from money; delete from money where name="wang"; savepoint delete_wang; select * from money; delete from money where name="xiong"; savepoint delete_xiong; select * from money; delete from money where id=1; savepoint delete_id1; select * from money; -- 返回到增長wu的時候 rollback to insert_wu; select * from money; -- 返回到增長chen的時候 rollback to insert_chen; select * from money; -- 返回到刪除wang的時候 rollback to delete_wang; select * from money; -- 返回到刪除xiong的時候 rollback to delete_xiong; select * from money;
import pymysql # 鏈接數據庫 xiong conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',passwd='root',db='xiong') #更改獲取數據結果的數據類型,默認是元組,能夠改成字典等:conn.cursor(cursor=pymysql.cursors.DictCursor) cursor = conn.cursor() # cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 建立表 new_table = """create table account( id INT primary key auto_increment, name VARCHAR(20), balance double)""" cursor.execute(new_table) # 向表account中插入數據 insert_data = """INSERT INTO account(name,balance) values ('alvin',5000), ('xialv',10000), ('xiong',15000), ('wang',4000)""" cursor.execute(insert_data) cursor.execute("select * from account") print(cursor.fetchall()) try: insertData1 = "INSERT INTO account (name,balance) VALUES ('oldboy',4000)" updateData2 = "update account set balance=balance-3000 where name='alvin'" updateData3 = "update account set balance=balance+3000 where name='xiong'" cursor.execute(insertData1) conn.commit() cursor.execute(updateData2) raise Exception #產生一個異常 cursor.execute(updateData3) cursor.close() conn.commit except Exception as e: print("撤銷事務以前") cursor.execute("select * from account") print(cursor.fetchall()) conn.rollback() conn.commit() print("撤銷事務以後") cursor.execute("select * from account") print(cursor.fetchall())
<1> 原子性(Atomicity):原子性是指事務是一個不可分割的工做單位,事務中的操做要麼都發生,要麼都不發生。安全
<2> 一致性(Consistency):事務先後數據的完整性必須保持一致。在事務執行以前數據庫是符合數據完整性約束的,不管事務是否執行成功,事務結束後的數據庫中的數據也應該是符合完整性約束的。在某一時間點,若是數據庫中的全部記錄都能保證知足當前數據庫中的全部約束,則能夠說當前的數據庫是符合數據完整性約束的。
好比刪部門表前應該刪掉關聯員工(已經創建外鍵),若是數據庫服務器發生錯誤,有一個員工沒刪掉,那麼此時員工的部門表已經刪除,那麼就不符合完整性約束了,因此這樣的數據庫也就性能太差啦!性能優化
<3>隔離性(Isolation):事務的隔離性是指多個用戶併發訪問數據庫時,一個用戶的事務不能被其它用戶的事務所幹擾,多個併發事務之間數據要相互隔離。服務器
<4>持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的,接下來即便數據庫發生故障也不該該對其有任何影響。session
3、隔離性:
將數據庫設計爲串行化程的數據庫,讓一張表在同一時間內只能有一個線程來操做。若是將數據庫設計爲這樣,那數據庫的效率過低了。因此數據庫的設計這沒有直接將數據庫設計爲串行化,而是爲數據庫提供多個隔離級別選項,使數據庫的使用者能夠根據使用狀況本身定義到底須要什麼樣的隔離級別。數據結構
不考慮隔離性可能出現的問題:併發
髒讀
--一個事務讀取到了另外一個事務未提交的數據,這是特別危險的,要盡力防止。 a 1000 b 1000 a: start transaction; update set money=money+100 where name=b; b: start transaction; select * from account where name=b;--1100 commit; a: rollback; b: start transaction; select * from account where name=b;--1000
不可重複讀
--在一個事務內讀取表中的某一行數據,屢次讀取結果不一樣。(一個事務讀取到了另外一個事務已經提交 -- 的數據--增長記錄、刪除記錄、修改記錄),在某寫狀況下並非問題,在另外一些狀況下就是問題。 a: start transaction; select 活期帳戶 from account where name=b;--1000 活期帳戶:1000 select 按期帳戶 from account where name=b;--1000 按期帳戶:1000 select 固定資產 from account where name=b;--1000 固定資產:1000 ------------------------------ b: start transaction; update set money=0 where name=b; commit; ------------------------------ select 活期+按期+固定 from account where name=b; --2000 總資產: 2000
虛讀
是指在一個事務內讀取到了別的事務插入的數據,致使先後讀取不一致。(一個事務讀取到了另外一個事務已經提交的數據---增長記錄、刪除記錄),在某寫狀況下並非問題,在另外一些狀況下就是問題。 b 1000 c 2000 d 3000 a: start transaction select sum(money) from account;---3000 3000 ------------------- d:start transaction; insert into account values(d,3000); commit; ------------------- select count(*)from account;---3 3 3000/3 = 1000 1000
四個隔離級別:
Serializable:可避免髒讀、不可重複讀、虛讀狀況的發生。(串行化)
Repeatable read:可避免髒讀、不可重複讀狀況的發生。(可重複讀)不能夠避免虛讀
Read committed:可避免髒讀狀況發生(讀已提交)
Read uncommitted:最低級別,以上狀況均沒法保證。(讀未提交)
安全性考慮:Serializable>Repeatable read>Read committed>Read uncommitted
數據庫效率:Read uncommitted>Read committed>Repeatable read>Serializable
通常狀況下,咱們會使用Repeatable read、Read committed mysql數據庫默認的數據庫隔離級別Repeatable read
mysql中設置數據庫的隔離級別語句:
set [global/session] transaction isolation level xxxx;
若是使用global則修改的是數據庫的默認隔離級別,全部新開的窗口的隔離級別繼承自這個默認隔離級別若是使用session修改,則修改的是當前客戶端的隔離級別,和數據庫默認隔離級別無關。當前的客戶端是什麼隔離級別,就能防止什麼隔離級別問題,和其餘客戶端是什麼隔離級別無關。
mysql中設置數據庫的隔離級別語句:
select @@tx_isolation;
索引在MySQL中也叫作「鍵」,是存儲引擎用於快速找到記錄的一種數據結構。索引對於良好的性能很是關鍵,尤爲是當表中的數據量愈來愈大時,索引對於性能的影響愈發重要。
索引優化應該是對查詢性能優化最有效的手段了。
索引可以輕易將查詢性能提升好幾個數量級。
索引至關於字典的音序表,若是要查某個字,若是不使用音序表,則須要從幾百頁中逐頁去查。
索引特色:建立與維護索引會消耗不少時間與磁盤空間,但查詢速度大大提升!
--建立表時 --語法: CREATE TABLE 表名 ( 字段名1 數據類型 [完整性約束條件…], 字段名2 數據類型 [完整性約束條件…], [UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [索引名] (字段名[(長度)] [ASC |DESC]) ); -------------------------------- --建立普通索引示例: CREATE TABLE emp1 ( id INT, name VARCHAR(30) , resume VARCHAR(50), INDEX index_emp_name (name) --KEY index_dept_name (dept_name) ); --建立惟一索引示例: CREATE TABLE emp2 ( id INT, name VARCHAR(30) , bank_num CHAR(18) UNIQUE , resume VARCHAR(50), UNIQUE INDEX index_emp_name (name) ); --建立全文索引示例: CREATE TABLE emp3 ( id INT, name VARCHAR(30) , resume VARCHAR(50), FULLTEXT INDEX index_resume (resume) ); --建立多列索引示例: CREATE TABLE emp4 ( id INT, name VARCHAR(30) , resume VARCHAR(50), INDEX index_name_resume (name, resume) ); --------------------------------- ---添加索引 ---CREATE在已存在的表上建立索引 CREATE [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 ON 表名 (字段名[(長度)] [ASC |DESC]) ; ---ALTER TABLE在已存在的表上建立索引 ALTER TABLE 表名 ADD [UNIQUE | FULLTEXT | SPATIAL ] INDEX 索引名 (字段名[(長度)] [ASC |DESC]) ; CREATE INDEX index_emp_name on emp1(name); ALTER TABLE emp2 ADD UNIQUE INDEX index_bank_num(band_num); -- 刪除索引 語法:DROP INDEX 索引名 on 表名 DROP INDEX index_emp_name on emp1; DROP INDEX bank_num on emp2;
--建立表 create table Indexdb.t1(id int,name varchar(20)); --存儲過程 delimiter $$ create procedure autoinsert() BEGIN declare i int default 1; while(i<500000)do insert into Indexdb.t1 values(i,'yuan'); set i=i+1; end while; END$$ delimiter ; --調用函數 call autoinsert(); -- 花費時間比較: -- 建立索引前 select * from Indexdb.t1 where id=300000;--0.32s -- 添加索引 create index index_id on Indexdb.t1(id); -- 建立索引後 select * from Indexdb.t1 where id=300000;--0.00s