mysql锁简谈_mysql锁简谈
1.mysql鎖,
作用:解決因資源共享而造成的并發問題。
實例:買最好一件衣服X
A: X 買: X加鎖----->試衣服……下單……付款……打包….------>X解鎖
B: X 買: 發現X已被加鎖,等待X解鎖,X已售空
分類 :
操作類型:
A.讀鎖(共享鎖):對同一個數據(衣服),多個讀操作可以同時進行,互不干擾
B.寫鎖(互斥鎖):如果當前寫操作沒有完畢(買衣服的一系列操作),則無法進行其他的讀操作,寫操作。
操作范圍:
A.表鎖:一次性對一張表整體加鎖.
如:MYISAM存儲引擎使用表鎖,開銷小,加鎖快,無死鎖;
但鎖的范圍大,容易發生鎖沖突,并發度低;
B.行鎖:一次性對一條數據加鎖
如:INNODB存儲引擎使用行鎖,開銷大,加鎖慢,容易出現死鎖;
但鎖的范圍較小,不易發生鎖沖突,并發度高(很小概率發生高并發問題:臟讀,幻讀,不可重復讀,丟失更新等)
實例:
表鎖: 自增操作mysql/sqlserver支持,Oracle需要借助于序列來實現自增
Create table tablelock
(
Id int primary key auto_increment,
Name varchar(20)
)engine myisam;
Insert into tablelock(name) values('a1')
Insert into tablelock(name) values('a2')
Insert into tablelock(name) values('a3')
Insert into tablelock(name) values('a4')
Insert into tablelock(name) values('a5')
查看加鎖的表: show open tables; desc emp;查表結構
增加鎖: locak table 表1 read/write , 表2 read/write , …..
回話1:session
加讀鎖:locak table tablelock read;
select * from tablelock; -----讀,可以
delete from tablelock where id=1;-------寫(增刪改),不可以
Select * from emp;-----讀,不可以
Delete from emp where eno=1;------寫,不可以
總結:會話1如果給A表加了讀鎖,則當前會話只能對A表進行讀操作,其他表都不能操作
會話2(其它會話):
Select * from tablelock;-------讀,可以
Delete from tablelock where id=1;-----寫,會“等待”會話1解鎖為止
Select * from emp;-------讀,可以
Delete from emp where eno=1;--------寫,可以
總結:會話1給A表加了鎖,其它會話的操作:
A.可以除了A表的其它表進行讀,寫操作
B.對A表:讀,可以,寫要等待釋放鎖
釋放鎖:會話1執行, unlock tables;
2.加寫鎖:
會話1:
lock table tablelock write;
當前會話1,可以對加了鎖的表進行任何操作(增刪改查),但是不能操作(增刪改查)其它表
其它會話2,對會話1中加寫鎖的表,可以進行增刪改查的前提是:等待會話1釋放寫鎖
MySQL表極鎖的鎖模式
MyISAM在執行查詢語句(SELECT)前,會自動給涉及的所有表加讀鎖,在執行更新操作 (DML)前,會自動給涉及的表加寫鎖。
所以對MyISAM表進行操作,會有以下情況:
A.對MyISAM表的讀操作(加讀鎖),不會阻塞其它進程(會話)對同一表的讀請求,但會阻塞對同一表的寫請求。只有當讀鎖釋放后,才會執行其它進程的寫操作。
B.對MyISAM表的寫操作(加寫鎖),會阻塞其它進程(會話)對同一表的讀和寫操作,只有當寫鎖釋放后,才會執行其它進程的讀寫操作。
分析表鎖定:
查看哪些表加了鎖:show open tables;----1代表被加了鎖
分析表鎖定的嚴重程度:show status like ‘%table%’;
Table_locks_immediate:即可能獲取到的鎖數
Table_locks_waited:需要等待的表鎖數(如果該值越大,說明存在越大的鎖競爭)
一般建議Table_locks_immediate/Table_locks_waited>5000,則建議采用InnoDB引擎,否則用MyISAM引擎
行表(InnoDB)
Create table linelock(
Id int(5) primary key auto_increment,
Name varchar(20)
)engine=innodb;
Insert into linelock (name) values('1');
Insert into linelock (name) values('2');
Insert into linelock (name) values('3');
Insert into linelock (name) values('4');
Insert into linelock (name) values('5');
------mysql默認自動commit;Oracle默認不會自動commit;
為了研究行鎖,暫時關閉commit;set autocommit=0;以后每條都要commit
會話1:寫操作
Insert into linelock values(6,'a6'); -----------關閉commit后,在緩存里,commit后才生效
會話2:寫操作同樣的數據
Update linelock set name='ax' where id=6;---------想更新id為6的數據,執行時出現被鎖狀態,直到其它會話釋放(commit)后才能操作(行鎖)
提交:commit;丟棄:rollback;
對行鎖情況:
1.如果會話x對數據a進行DML操作(研究時關閉了自動commit的情況下),則其它會話必須等到會話x結束事務(commit/rollback)后,才能對數據a進行操作。
2.表鎖 是通過unlock tables; ,也可以通過事務解鎖。行鎖 是通過事務解鎖。
行鎖,一次鎖一行數據,因此,如果操作的是不同數據,則不干擾。
3.行鎖的注意事項:
A.如果沒索引,則行鎖會轉為表鎖
Show index from linelock;
Alter table linelock add index idx_linelock_name(name);
會話1:寫操作
Update linelock set name='ai' where name='3';
會話2:寫操作,不同的數據
Update linelock set name='aix' where name='4';
會話1:寫操作
update linelock set name='ai' where name=3;
會話2:寫操作,不同數據
update linelock set name='aix' where name=4;
-------->可以發現,數據被阻塞了(加鎖)
-------->原因:如果索引類 發生了類型轉換,則索引失效。因此此次操作,會從行鎖轉為表鎖。
B.行鎖的一種特殊情況:間隙鎖:值在范圍里,但卻不存在。
此時linelock表中,沒有id=7的數據
Update linelock set name='x' where id>1 and id<9;
mysql會自動給間隙加鎖---->間隙鎖,給id=7的數據加間隙鎖(行鎖)。
行鎖:如果有where,則實際加鎖的范圍就是where后面的范圍(不是實際的值)
行鎖:innodb默認采用行鎖
缺點:比表鎖性能消耗大
優點:并發能力強,效率高
建議:高并發用innodb,否則用myisam
分析:show status like '%innodb_row_lock%';
Innodb_row_lock_current_waits: 當前正在等待鎖的數量
Innodb_row_lock_time: 等待總時長,從系統啟動到現在一共等待的時間
Innodb_row_lock_time_avg:平均等待時間
Innodb_row_lock_time_max:最長等待時間
Innodb_row_lock_waits: 系統啟動到現在一共等待的次數
查詢行鎖:
關閉commit自動提交:
set autocommit;
start transaction;
begin;
for update對query語句加鎖
Select * from linelock where id=2 for update
4.主從復制:
優點:負載均衡
失敗遷移
Windows:mysql 主
Linux:mysql 從
(版本最好相近或相同)
圖形客戶端工具
SQLyog, Navicat
如果要遠程連接數據庫,則需要授權遠程訪問。
Windows:安裝時選擇可以遠程訪問
Linux:GRANT ALL PRIVILEGES ON *.* TO 'root' @'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;
關閉防火墻:service iptables stop
主機Windows192.168.2.2:授權那個數據庫作為自己的slave
GRANT REPLICATION slave ,reload, super ON *.* TO 'root'@'192.168.2.%' IDENTIFIED BY 'root';
fulsh privileges;
show master status;
從機linux:授權那個數據庫作為自己的master
CHANGE MASTER TO MASTER_HOST ='192.168.2.2',MASTER_USER='root', MASTER_PASSWORD='root' ,MASTER_PORT=3306,
master_log_file='mysql-bin.000002', master_log_pos=667;
5.主從復制:
同步的核心:二進制文件binary log
對數據庫的增刪改查的操作都會備份到二進制文件里
從數據庫的I/O線程會從主數據庫讀二進制文件
Relay log通過sql線程寫到從數據庫
1.master將改變的數記錄在本地的二進制日志中(binary log):
該過程稱之為二進制日志事件
2.slave將master的binary log拷貝到自己的relay log(中繼日志文件)中
3.中繼日志事件,將數據讀取到自己的數據庫之中
mysql主從復制是異步,串行化的,有延遲的
master:slave=1:n
配置:
Windows:主mysql,my.ini
Linux:從mysql,my.cnf
配置前,為了無誤,先將各防火墻,權限(遠程訪問)處理好
主mysql,my.ini配置文件中:
[mysqld]下,server-id=1
log-bin="mysql安裝目錄/data/mysql-bin" ----二進制文件,注意是/,不是\
log-error="mysql安裝目錄/data/mysql-error" ---錯誤記錄文件
binlog-ignore-db=mysql ------主從同步時,忽略的數據庫
binlog-do-db=test ------主從同步時,同步哪些數據
Windows主mysql授權那臺從計算機
GRANT REPLICATION slave ,reload, super ON *.* TO 'root'@'192.168.2.%' IDENTIFIED BY 'root';
fulsh privileges;
show master status; ----查看主數據庫的狀態
File ,Position , Binlog_Do_DB , Binlog_Ignore_DB
Mysql-bin.000001 , 575 , test , mysql
重啟后二進制文件才有mysql-bin,mysql-error
File , Position(107)要變,每次在左主從同步前,需要觀察主機狀態的最新值
從mysql, my.cnf配置文件中:
[mysqld]下,server-id=2
log-bin=mysql-bin
replicate-do-db=test
linux中的從mysql授權那臺主計算機
從機linux:授權那個數據庫作為自己的master
CHANGE MASTER TO MASTER_HOST ='192.168.2.2',MASTER_USER='root', MASTER_PASSWORD='root' ,MASTER_PORT=3306,
master_log_file='mysql-bin.000001', master_log_pos=107;
如果報錯:This operation cannot be performed with a running slave ; run STOP SLAVE first
第一次不報錯,第二第三次出這個錯,
先STOP SLAVE; 再執行上面從mysql授權語句
開啟主從同步:
從機Linux:start slave ;
檢驗狀態: show slave status \G
主要觀察2個,slave_sql_running,slave_io_running , 要都是yes
如果不是yes,則看下方的日志 last_io_error,主從使用了相同的server-id,
檢查:在主從中分別查看server-id:show variables like '%server_id%' ; 發現確實都是1,但配置時是1,2,版本bug
Windows:5.5.56 ;Linux:5.5.58,可能5.5.58版本兼容性問題,或者是版本不同問題
解決:文件改不行,現在用全局變量改:set global server_id=2 ; (linux) , 設置了后關閉再開啟
演示:主mysql在test數據庫中新增表,插入數據,從mysql自動同步數據了.自此主從同步成功。
總結
以上是生活随笔為你收集整理的mysql锁简谈_mysql锁简谈的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python圆的半径计算圆的周长列表_p
- 下一篇: 家常卤牛肉的做法?