2019-03-13

1、整理今天所學(xué)的知識(shí)點(diǎn)

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

1.主從復(fù)制

基本步驟:

1. 在主服務(wù)器上,必須開啟二進(jìn)制日志機(jī)制和配置一個(gè)獨(dú)立的ID

2. 在每一個(gè)從服務(wù)器上,配置一個(gè)唯一的ID,創(chuàng)建一個(gè)用來專門復(fù)制主服務(wù)器數(shù)據(jù)的賬號(hào)

3. 在開始復(fù)制進(jìn)程前,在主服務(wù)器上記錄二進(jìn)制文件的位置信息

4. 如果在開始復(fù)制之前,數(shù)據(jù)庫中已經(jīng)有數(shù)據(jù),就必須先創(chuàng)建一個(gè)數(shù)據(jù)快照(可以使用mysqldump導(dǎo)出數(shù)據(jù)庫,或者直接復(fù)制數(shù)據(jù)文件)

5. 配置從服務(wù)器要連接的主服務(wù)器的IP地址和登陸授權(quán),二進(jìn)制日志文件名和位置

在主服務(wù)器Ubuntu上進(jìn)行備份,執(zhí)行命令:

mysqldump -uroot -pmysql --all-databases --lock-all-tables > ~/master_db.sql

說明

-u :用戶名

-p :示密碼

--all-databases :導(dǎo)出所有數(shù)據(jù)庫

--lock-all-tables :執(zhí)行操作時(shí)鎖住所有表,防止操作時(shí)有數(shù)據(jù)修改

~/master_db.sql :導(dǎo)出的備份數(shù)據(jù)(sql文件)位置,可自己指定

在從服務(wù)器Windows上進(jìn)行數(shù)據(jù)還原

登陸數(shù)據(jù)庫,然后運(yùn)行

source master_db.sql

配置主服務(wù)器master(Ubuntu中的MySQL)

編輯設(shè)置mysqld的配置文件,設(shè)置log_bin和server-id

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

在最后添加這兩句代碼

server-id = 1

log_bin = master-bin


重啟服務(wù)器(修改配置都要重新開啟服務(wù)器)

Slave從服務(wù)器配置

1、修改配置文件

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

然后在最后加入三行代碼如下:

server-id = 2

relay-log = slave-relay-bin

relay-log-index = slave-relay-bin.index


4.查看主服務(wù)器狀態(tài):

show master status;


Slave從服務(wù)器配置

1、修改配置文件

sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf

然后在最后加入三行代碼如下:

server-id = 2

relay-log = slave-relay-bin

relay-log-index = slave-relay-bin.index


2、重啟服務(wù)

sudo service mysql restart

登錄Slave從服務(wù)器,運(yùn)行命令

change master to master_host='192.168.12.39',master_port=3306,master_user='masterbackup',master_password='masterbackup',master_log_file='master-bin.000006',master_log_pos=310;


啟動(dòng)Slave數(shù)據(jù)同步


查看Slave信息


如果有兩個(gè)yes,表示成功。

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、


2.悲觀鎖和樂觀鎖

1.3.11.1 悲觀鎖(Pessimistic Lock)

在查詢的時(shí)候,鎖起來,事務(wù)結(jié)束后,釋放。

悲觀鎖的特點(diǎn)是先獲取鎖,再進(jìn)行業(yè)務(wù)操作,即“悲觀”的認(rèn)為獲取鎖是非常有可能失敗的,因此要先確保獲取鎖成功再進(jìn)行業(yè)務(wù)操作。通常所說的“一鎖二查三更新”即指的是使用悲觀鎖。通常來講在數(shù)據(jù)庫上的悲觀鎖需要數(shù)據(jù)庫本身提供支持,即通過常用的select … for update操作來實(shí)現(xiàn)悲觀鎖。當(dāng)數(shù)據(jù)庫執(zhí)行select for update時(shí)會(huì)獲取被select中的數(shù)據(jù)行的行鎖,因此其他并發(fā)執(zhí)行的select… for update如果試圖選中同一行則會(huì)發(fā)生排斥(需要等待行鎖被釋放),因此達(dá)到鎖的效果。select for update獲取的行鎖會(huì)在當(dāng)前事務(wù)結(jié)束時(shí)自動(dòng)釋放,因此必須在事務(wù)中使用。

這里需要注意的一點(diǎn)是不同的數(shù)據(jù)庫對(duì)select for update的實(shí)現(xiàn)和支持都是有所區(qū)別的,例如oracle支持select for update no wait,表示如果拿不到鎖立刻報(bào)錯(cuò),而不是等待,mysql就沒有no wait這個(gè)選項(xiàng)。另外mysql還有個(gè)問題是select for update語句執(zhí)行中所有掃描過的行都會(huì)被鎖上,這一點(diǎn)很容易造成問題。因此如果在mysql中用悲觀鎖務(wù)必要確定走了索引,而不是全表掃描。

1.3.11.2 樂觀鎖(Optimistic Lock)

查詢的時(shí)候,不需要操作,更改的時(shí)候再判斷。

樂觀鎖的特點(diǎn)先進(jìn)行業(yè)務(wù)操作,不到萬不得已不去拿鎖。即“樂觀”的認(rèn)為拿鎖多半是會(huì)成功的,因此在進(jìn)行完業(yè)務(wù)操作需要實(shí)際更新數(shù)據(jù)的最后一步再去拿一下鎖就好。

樂觀鎖在數(shù)據(jù)庫上的實(shí)現(xiàn)完全是邏輯的,不需要數(shù)據(jù)庫提供特殊的支持。一般的做法是在需要鎖的數(shù)據(jù)上增加一個(gè)版本號(hào),或者時(shí)間戳,然后按照如下方式實(shí)現(xiàn):

1. SELECT data AS old_data, version AS old_version FROM …;

2. 根據(jù)獲取的數(shù)據(jù)進(jìn)行業(yè)務(wù)操作,得到new_data和new_version

3. UPDATE SET data = new_data, version = new_version WHERE version = old_version

if (updated row > 0) {

? ? // 樂觀鎖獲取成功,操作完成

} else {

? ? // 樂觀鎖獲取失敗,回滾并重試

}

樂觀鎖是否在事務(wù)中其實(shí)都是無所謂的,其底層機(jī)制是這樣:在數(shù)據(jù)庫內(nèi)部update同一行的時(shí)候是不允許并發(fā)的,即數(shù)據(jù)庫每次執(zhí)行一條update語句時(shí)會(huì)獲取被update行的寫鎖,直到這一行被成功更新后才釋放。因此在業(yè)務(wù)操作進(jìn)行前獲取需要鎖的數(shù)據(jù)的當(dāng)前版本號(hào),然后實(shí)際更新數(shù)據(jù)時(shí)再次對(duì)比版本號(hào)確認(rèn)與之前獲取的相同,并更新版本號(hào),即可確認(rèn)這之間沒有發(fā)生并發(fā)的修改。如果更新失敗即可認(rèn)為老版本的數(shù)據(jù)已經(jīng)被并發(fā)修改掉而不存在了,此時(shí)認(rèn)為獲取鎖失敗,需要回滾整個(gè)業(yè)務(wù)操作并可根據(jù)需要重試整個(gè)過程。

1.3.11.3 總結(jié)

樂觀鎖在不發(fā)生取鎖失敗的情況下開銷比悲觀鎖小,但是一旦發(fā)生失敗回滾開銷則比較大,因此適合用在取鎖失敗概率比較小的場(chǎng)景,可以提升系統(tǒng)并發(fā)性能

樂觀鎖還適用于一些比較特殊的場(chǎng)景,例如在業(yè)務(wù)操作過程中無法和數(shù)據(jù)庫保持連接等悲觀鎖無法適用的地方

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

3.引擎

4.pymysql的安裝及增刪改查

import pymysql

# 獲取連接對(duì)象

my_conn = pymysql.connect(

? ? host='192.168.0.138',

? ? user='root',

? ? password='root',

? ? database='mydb',

? ? port=3306,

? ? charset='utf8'

)

# 獲取可執(zhí)行sql的對(duì)象

my_cursor = my_conn.cursor()

# sql語句

sql = 'insert into t_user(name,pwd) values("{}","{}")'.format('laowang', '123456')

print(sql)

# 執(zhí)行sql語句

num = my_cursor.execute(sql)

print(num)

# 提交

my_conn.commit()

# 關(guān)閉

my_cursor.close()

my_conn.close()

、、、、、、、、、、、、、、、、、、、、、、、、、、

1.增

import pymysql

# 獲取連接對(duì)象

my_conn = pymysql.connect(

? ? host='192.168.0.138',

? ? user='root',

? ? password='root',

? ? database='mydb',

? ? port=3306,

? ? charset='utf8'

)

# 獲取可執(zhí)行sql的對(duì)象

my_cursor = my_conn.cursor()

# sql語句

sql = 'insert into t_user(name,pwd) values("{}","{}")'.format('laowang', '123456')

print(sql)

# 執(zhí)行sql語句

num = my_cursor.execute(sql)

print(num)

# 提交

my_conn.commit()

# 關(guān)閉

my_cursor.close()

my_conn.close()


2.改

import pymysql

my_conn = pymysql.connect(

? ? host='192.168.0.138',

? ? user='root',

? ? password='root',

? ? database='mydb',

? ? port=3306,

? ? charset='utf8'

)

# 獲取可執(zhí)行sql的對(duì)象

my_cursor = my_conn.cursor()

sql1 = 'update bank set money = money-20 where id = 1'

sql2 = 'update bank set money = money+20 where id = 2'

#捕捉異常

try:

? ? my_cursor.execute(sql1)

? ? my_cursor.execute(sql2)

? ? my_conn.commit()

except Exception as ex:

? ? my_conn.rollback()

finally:

? ? my_cursor.close()

? ? my_conn.close()



3.查
import pymysql

def f1():

? ? # 獲取連接對(duì)象

? ? my_conn = pymysql.connect(

? ? ? ? host='192.168.0.138',

? ? ? ? user='root',

? ? ? ? password='root',

? ? ? ? database='mydb',

? ? ? ? port=3306,

? ? ? ? charset='utf8'

? ? )

? ? # 獲取可執(zhí)行sql的對(duì)象

? ? my_cursor = my_conn.cursor()

? ? # sql語句

? ? sql = 'select empno,ename,hiredate from EMP'

? ? # 執(zhí)行sql語句

? ? my_cursor.execute(sql)

? ? # 獲取查詢數(shù)據(jù)

? ? rows = my_cursor.fetchall()

? ? for empno, ename, hiredate in rows:

? ? ? ? print(empno, ename, hiredate)

? ? # 關(guān)閉

? ? my_cursor.close()

? ? my_conn.close()

def f2():

? ? my_conn = pymysql.connect(

? ? ? ? host='192.168.0.138',

? ? ? ? user='root',

? ? ? ? password='root',

? ? ? ? database='mydb',

? ? ? ? port=3306,

? ? ? ? charset='utf8'

? ? )

? ? # 獲取可執(zhí)行sql的對(duì)象

? ? my_cursor = my_conn.cursor()

? ? sql = 'select empno,ename,hiredate from EMP'

? ? my_cursor.execute(sql)

? ? # 獲取查詢數(shù)據(jù)

? ? row = my_cursor.fetchone()

? ? print(row)

? ? my_cursor.close()

? ? my_conn.close()

if __name__ == '__main__':

? ? # f2()

? ? f1()


4.

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

2、新建一個(gè)學(xué)生表(姓名,密碼,出生日期,地址),使用python代碼完成循環(huán)插入5個(gè)學(xué)生信息。

要求如下:

1、姓名唯一,如果重復(fù)提示重復(fù)輸入,直到用戶輸入正確為止。

2、出生日期要求用戶輸入的格式y(tǒng)yyy-mm-dd,如果錯(cuò)誤,重新輸入,直到用戶輸入正確為止。

3、5個(gè)學(xué)生輸入完畢后,顯示5個(gè)學(xué)生的信息。


import pymysql

my_conn = pymysql.connect(

? ? host='192.168.0.138',

? ? user='root',

? ? password='root',

? ? database='mydb',

? ? port=3306,

? ? charset='utf8'

)

my_cursor = my_conn.cursor()

try:

? ? for i in range(1):

? ? ? ? id = input("請(qǐng)輸入學(xué)生id")

? ? ? ? name= input("請(qǐng)輸入學(xué)生姓名")

? ? ? ? pwd = input("請(qǐng)輸入學(xué)生密碼")

? ? ? ? hiredate = input("請(qǐng)輸入學(xué)生出生日期")

? ? ? ? addres = input("請(qǐng)輸入學(xué)生地址")

? ? sql = 'insert into student(id,name,pwd,hiredate,addres)? values(%s,%s,%s,%s,%s)'

? ? num = my_cursor.execute(sql,[id,name,pwd,hiredate,addres])

? ? print(num)

? ? my_conn.commit()

except:

? ? print("請(qǐng)輸入正確的出生日期")

? ? my_cursor.close()

? ? my_conn.close()


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容