mysql
致使結果:linux
鏈接數過多,致使鏈接不上數據庫,業務沒法正常進行sql
shell
#默認鏈接數 mysql> show variables like '%max_connection%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+ 1 row in set (0.00 sec)
解決問題思路:數據庫
一、首先先要考慮在咱們 MySQL 數據庫參數文件裏面,對應的 max_connections
這個參數值是否是設置的過小了,致使客戶端鏈接數超過了數據庫所承受的最大值。vim
該值默認大小是 151,能夠根據實際狀況進行調整。centos
對應解決辦法:set global max_connections=500
bash
服務器
因此這又反映出了,在新上線一個業務系統的時候,要作好壓力測試。保證後期對數據庫進行優化調整。session
結果:
若是寫入大數據時,由於默認的配置過小,插入和更新操做會由於 max_allowed_packet 參數限制,而致使失敗。
當一個MySQL客戶或mysqld服務器獲得一個max_allowed_packet個字節長的包, 它發出一個Packet too large錯誤並終止鏈接。
mysql> show variables like 'max_allowed_packet'; +--------------------+---------+ | Variable_name | Value | +--------------------+---------+ | max_allowed_packet | 4194304 | +--------------------+---------+
默認是4M大小
可使用mysqld的命令行選項設置max_allowed_packet爲一個更大的尺寸。 例如, 若是將一個全長的BLOB存入一張表中, 須要用max_allowed_packet=24M選項來啓動mysql。
Max_allowed_packet的取值範圍是1024B~1GB
固然不要亂設置,根據具體環境要求,設置太大業務
# 具體設置max_allowed_packet大小 mysql> set @@global.max_allowed_packet= #在my.cnf 加入這個 max_allowed_packet= 10M
若是是靜態參數仍是要重啓服務纔會生效,動態參數則不用
#默認鏈接數 mysql> show variables like '%max_connection%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+ 1 row in set (0.00 sec) #修改鏈接數爲500 mysql> set @@global.max_connections=500; Query OK, 0 rows affected (0.00 sec) #查看是否修改爲功 mysql> show variables like '%max_connection%'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 500 | +-----------------+-------+ # 在my.cnf 的[mysqld]下面加上 max_connections=500就能夠了,也不用重啓服務
忘記了MySQL的root用戶的口令 在my.cnf中添加skip-grant-tables=1選項重啓mysqld
[root@mysql-150 ~]# mysql -u root -h 127.0.0.1 mysql> flush privileges; mysql> grant all privileges on *.* to root@'localhost' identified by '456789'; mysql> exit # 在my.cnf 將skip-grant-tables=1選項去掉 # 重啓mysqld以後就能夠用最新的密碼登陸 [root@mysql-150 ~]# vim /etc/my.cnf [root@mysql-150 ~]# service mysql restart Shutting down MySQL............ SUCCESS! Starting MySQL. SUCCESS! [root@mysql-150 ~]# mysql -u root -p456789 -h 127.0.0.1
# 建立一個用戶 mysql> create user keme@'localhost' identified by '123456'; # 給一個只讀權限 mysql> grant select on *.* to keme@'localhost'; # 能夠從本地登陸 [root@mysql-150 ~]# mysql -u keme -p123456 # 把keme@'localhost' 給lock住,不讓其使用 mysql> alter user keme@'localhost' account lock; # 在看看能不能從本地登陸 [root@mysql-150 ~]# mysql -u keme -p123456 mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 3118 (HY000): Access denied for user 'keme'@'localhost'. Account is locked. # 查看該用戶是否鎖定 mysql> select host,user,account_locked from mysql.user where user='keme'; +-----------+------+----------------+ | host | user | account_locked | +-----------+------+----------------+ | localhost | keme | Y | +-----------+------+----------------+ Y已鎖定 # 而後解鎖該keme用戶 mysql> alter user keme@'localhost' account unlock; # 再去登陸keme用戶 [root@mysql-150 ~]# mysql -u keme -p123456
臨時添加:
# 首先要肯定mysql 的安裝位置 shell> export PATH=$PATH:/usr/local/mysql/bin
永久設置:
# 在/etc/profile 中末尾添加 PATH=$PATH:$HOME/bin:/usr/local/mysql/bin export PATH 保存退出後執行: source /etc/bash_profile便可。
模式定義MySQL應支持哪些SQL語法, 以及應執行哪一種數據驗證檢查。 這樣能夠更容易地在不一樣的環境中使用MySQL, 並結合其它數據庫服務器使用MySQL。
查看當前的sql_mode
mysql> show variables like 'sql_mode'; +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | Variable_name | Value | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | sql_mode | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +---------------+-------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select @@sql_mode; +-------------------------------------------------------------------------------------------------------------------------------------------+ | @@sql_mode | +-------------------------------------------------------------------------------------------------------------------------------------------+ | ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION | +-------------------------------------------------------------------------------------------------------------------------------------------+
更改語法和行爲, 使其更符合標準SQL。
sql mode經常使用值
但這有個條件:若是查詢是主鍵列或是惟一索引且非空列,分組列根據主鍵列或者惟一索引且空(null)則sql 分組查詢有效
該值影響自增加列的插入。默認設置下,插入0或NULL表明生成下一個自增加值。若是用戶但願插入的值爲0,而該列又是自增加的,那麼這個選項就有用了。
爲事務存儲引擎啓用嚴格模式, 也可能爲非事務存儲引擎啓用嚴格模式。
嚴格模式控制MySQL如何處理非法或丟失的輸入值。 有幾種緣由可使一個值爲非法。 例如, 數據類型錯 誤, 不適合列, 或超出範圍。 當新插入的行不包含某列的沒有顯示定義DEFAULT子句的值,則該值被丟失。 對於事務表, 當啓用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時, 若是語句中有非法或丟失值, 則會出現錯誤。 語句被放棄並回滾。
在嚴格模式下,不容許日期和月份爲零
設置該值,mysql數據庫不容許插入零日期,插入零日期會拋出錯誤而不是警告。
在INSERT或UPDATE過程當中,若是數據被零除,則產生錯誤而非警告。若是未給出該模式,那麼數據被零除時MySQL返回NULL
禁止GRANT建立密碼爲空的用戶
若是須要的存儲引擎被禁用或未編譯,那麼拋出錯誤。不設置此值時,用默認的存儲引擎替代,並拋出一個異常
將」||」視爲字符串的鏈接操做符而非或運算符,這和Oracle數據庫是同樣的,也和字符串的拼接函數Concat相相似
舉例:
# 建立一個測試表 CREATE TABLE `employee` ( `eid` int(11) NOT NULL, `ename` varchar(64) DEFAULT NULL, `sex` int(11) DEFAULT NULL, PRIMARY KEY (`eid`) ) ENGINE=InnoDB; # 插入幾條數據 insert into employee (eid,ename,sex) values (1,'keme',18),(2,'xixi',22),(3,'yj',18),(4,'kk',18),(5,'yy',18),(6,'xx',35); # 設置當前會話的sql_mode爲以下 mysql> set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; mysql> select eid,ename,count(*) from employee group by ename; +-----+-------+----------+ | eid | ename | count(*) | +-----+-------+----------+ | 1 | keme | 1 | | 4 | kk | 1 | | 2 | xixi | 1 | | 6 | xx | 1 | | 3 | yj | 1 | | 5 | yy | 1 | +-----+-------+----------+ # 從新設置當前的sql_mode 爲以下 mysql> set @@sql_mode='ONLY_FULL_GROUP_BY'; mysql> select eid,ename,count(*) from employee group by ename; ERROR 1055 (42000): Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'beta.employee.eid' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by mysql> select eid,ename ,count(*) from employee group by eid; +-----+-------+----------+ | eid | ename | count(*) | +-----+-------+----------+ | 1 | keme | 1 | | 2 | xixi | 1 | | 3 | yj | 1 | | 4 | kk | 1 | | 5 | yy | 1 | | 6 | xx | 1 | +-----+-------+----------+ 6 rows in set (0.00 sec) mysql> set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; mysql> insert into employee values(7,'ke','male'); ERROR 1366 (HY000): Incorrect integer value: 'male' for column 'sex' at row 1 mysql> set @@sql_mode='ANSI'; Query OK, 0 rows affected (0.00 sec) mysql> select @@sql_mode; +--------------------------------------------------------------------------------+ | @@sql_mode | +--------------------------------------------------------------------------------+ | REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI | +--------------------------------------------------------------------------------+ #改爲ANSI模式就能夠插入成功了,只不過識別成了0 mysql> insert into employee values(7,'ke','male'); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> select * from employee where eid=7; +-----+-------+------+ | eid | ename | sex | +-----+-------+------+ | 7 | ke | 0 | +-----+-------+------+ 1 row in set (0.00 sec) mysql> set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select @@sql_mode; +--------------------------------------------+ | @@sql_mode | +--------------------------------------------+ | STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION | +--------------------------------------------+ 1 row in set (0.00 sec) mysql> insert into employee values (8,'ww',17/0); Query OK, 1 row affected (0.00 sec) mysql> select * from employee where eid=8; +-----+-------+------+ | eid | ename | sex | +-----+-------+------+ | 8 | ww | NULL | +-----+-------+------+ mysql> set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select @@sql_mode; +-----------------------------------------------------------------------+ | @@sql_mode | +-----------------------------------------------------------------------+ | STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | +-----------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> insert into employee values (9,'ee',18/0); ERROR 1365 (22012): Division by 0 mysql> alter table employee modify ename varchar(5); mysql> set @@sql_mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'; mysql> insert into employee values (9,'qweradsf',11); ERROR 1406 (22001): Data too long for column 'ename' at row 1 mysql> set @@sql_mode='ANSI'; mysql> insert into employee values (9,'qweradsf',11); mysql> select * from employee where eid=9; +-----+-------+------+ | eid | ename | sex | +-----+-------+------+ | 9 | qwera | 11 | +-----+-------+------+ mysql> set @@sql_mode='TRADITIONAL'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> select @@sql_mode; TRADITIONAL模式有以下值: |STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
MAX_UPDATES_PER_HOUR:一個用戶在一個小時內能夠執行修改的次數(僅包含修 改數據庫或表的語句)
MAX_CONNECTIONS_PER_HOUR:容許用戶每小時鏈接的次數
MAX_USER_CONNECTIONS:一個用戶能夠在同一時間連MySQL實例的數量
經過執行create user/alter user設置/修改用戶的資源限制
# 建立一個用戶並設置其資源限制 CREATE USER 'keme1'@'localhost' IDENTIFIED BY '123456' WITH MAX_QUERIES_PER_HOUR 20 MAX_UPDATES_PER_HOUR 10 MAX_CONNECTIONS_PER_HOUR 5 MAX_USER_CONNECTIONS 2; #keme1 這個用戶 一個小時能夠查詢20次, 修改10次,一個小時能夠鏈接5次,同一時刻只容許兩個用戶 #取消某項資源限制既是把原先的值修改爲0 mysql> alter user 'keme1'@'localhost' WITH MAX_CONNECTIONS_PER_HOUR 0; # 當針對某個用戶的max_user_connections非0時, 則忽略全局系統參數max_user_connections, 反之則全局系統參數生效
在確保主從數據一致性的前提下,能夠在從庫進行錯誤跳過。
像從庫若是不提供什麼服務的話能夠在從庫中開啓 read_only 參數,禁止在從庫進行寫入操做,還有用戶必須沒有super 權限,設置read_only纔會生效。
這是正常的狀態
10.0.0.150 是主
10.0.0.151 是從
先模擬故障
# 這是本次的表結構 mysql> show create table students; | students | CREATE TABLE `students` ( `sid` int(11) NOT NULL, `sname` varchar(20) DEFAULT NULL, `sex` int(11) DEFAULT NULL, PRIMARY KEY (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 #主庫執行,是個空表 mysql> select * from students; Empty set (0.00 sec) #在從庫 ,給students 加1條數據: mysql> insert into students values (1,'keme',0); mysql> show slave status\G; ... Slave_IO_Running: Yes Slave_SQL_Running: Yes ... 看主從狀態是正常的 # 從庫查看students 數據 mysql> select * from students; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 1 | keme | 0 | +-----+-------+------+ # 在主庫查看students 表 mysql> select * from students; Empty set (0.00 sec) # 插入相同主鍵的值 mysql> insert into students values (1,'keme',1); # 查看students表 mysql> select * from students; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 1 | keme | 1 | +-----+-------+------+ # 查看從庫狀態 mysql> show slave status\G; ... Slave_IO_Running: Yes Slave_SQL_Running: No Last_SQL_Error: Could not execute Write_rows event on table beta.students; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000023, end_log_pos 11789 ... # 主從狀態不一致了,形成的緣由是主鍵衝突
解決辦法
# 中止從庫 mysql> stop slave; # 在從庫刪除主鍵衝突的那條語句, 把主庫執行的那條語句在從庫執行 mysql> delete from students where sid=1; mysql> insert into students values (1,'keme',1); # 同步跳過臨時錯誤 mysql> set global sql_slave_skip_counter = 1; mysql> start slave; mysql> show slave status\G; ... Slave_IO_Running: Yes Slave_SQL_Running: Yes ... # 主庫再次插入數據,看看從庫是否是可以同步 mysql> insert into students values (2,'keme',1); # 從庫查看 mysql> select * from students; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 1 | keme | 1 | | 2 | keme | 1 | +-----+-------+------+ 2 rows in set (0.00 sec) # OK,同步成功了, 通常主從錯誤也就解決了
首先主從問題不一致了,你的監控預警機制了,給你發短信或者釘釘,這時候你應該儘快去修復從庫,好比就像上面跳過臨時同步錯誤,暫時讓其恢復正常同步。
如今修改個人主從模式爲GTID,這是個人測試環境隨便改,
enforce_gtid_consitency=on :使用GTID模式複製時,須要開啓此參數,用來保證GTID的一致性。
log-bin=on :Msql 作主從必須開啓binlog
log-slave-updates=1 :以爲slave 從master 接收到的更新且執行完以後,執行的binlog是否記錄到slave的binlog中,建議開啓
binlog_format=row :強烈建議binlog_format使用row格式 在mysql 5.7.6 版本之後默認就是row
skip-slave-start=1 :當slave 數據庫啓動的時候,slave 不會自動開啓複製
主庫操做,在[mysqld] 加一下參數,我這個作過主從, 只加一部分參數
# my.cnf 中內容 [mysqld] gtid-mode=on enforce-gtid-consistency=on log-slave-updates=1
從庫操做
# my.cnf 中內容 [mysqld] gtid-mode=on enforce-gtid-consistency=on log-slave-updates=1 skip-slave-start=1
重啓主從數據庫
在從庫 操做從新設置主從庫的複製關係
mysql> CHANGE MASTER TO MASTER_HOST = '10.0.0.150', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = '123456', MASTER_AUTO_POSITION = 1; mysql> start slave; #查看主從狀態 mysql> show slave status\G; ... Slave_IO_Running: Yes Slave_SQL_Running: Yes ...
若是是在GTID模式下出現複製報錯, 則使用SQL_SLAVE_SKIP_COUNTER語句會報錯
在GTID 模式的複製狀況下,若是slave 發生錯誤,則能夠經過跳過該事務的方式恢復主從複製。
如今人爲製造slave錯誤
# 在從庫的sutdents 表插入一條數據 mysql> select * from students; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 1 | keme | 1 | | 2 | keme | 1 | +-----+-------+------+ mysql> insert into students values (3,'keme',0); # 在查看從庫的數據 mysql> select * from students; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 1 | keme | 1 | | 2 | keme | 1 | | 3 | keme | 0 | +-----+-------+------+ # 主庫也插入主鍵爲3這條數據,引起主從同步錯誤 mysql> insert into students values (3,'keme',1);
主從報錯了:
開始位置(Exec_Master_Log_Pos)是154 ,結束位置是(end_log_pos ) 395,能夠去主庫分析下binlog ,看一下發生衝突的事務是哪一個。
能夠看到接收而且執行了GTID事件 是
從庫執行了這些 5a13910d-1496-11e9-8375-000c29f859ce:1-3, f6c31435-38dd-11e9-ac93-000c299bcbee:1-53096 收到卻沒執行的事務號: Retrieved_Gtid_Set: f6c31435-38dd-11e9-ac93-000c299bcbee:53097
mysql> select * from students where sid=3; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 3 | keme | 0 | +-----+-------+------+
基於GTID模式的複製,跳過一個事務,須要利用一個空事務來完成。
mysql> stop slave; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> set GTID_NEXT='f6c31435-38dd-11e9-ac93-000c299bcbee:53097'; Query OK, 0 rows affected (0.00 sec) mysql> begin;commit; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> set GTID_NEXT='AUTOMATIC'; Query OK, 0 rows affected (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec)
查看slave 狀態
哪主從庫數據是否一致,就看3那條
# 主庫數據 mysql> select * from students where sid=3; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 3 | keme | 1 | +-----+-------+------+ #從庫數據 mysql> select * from students where sid=3; +-----+-------+------+ | sid | sname | sex | +-----+-------+------+ | 3 | keme | 0 | +-----+-------+------+
1 手動修改或者插入
2 用pt用具 來修復或者檢查不一致數據
因爲我這是個人本地環境,我只手動修改數據,再看主從狀態
mysql> update students set sex=1 where sid=3; Query OK, 1 row affected (0.03 sec) Rows matched: 1 Changed: 1 Warnings: 0
注:不止是要主從解決錯誤,還要主從數據的一致性
若是是生產的核心庫主從不一致,必定要查明緣由,否則總是 dba 或者運維 背鍋
還有若是主從不一致性實在是太多太多不一致了,就重作數據庫吧
若是檢查的數據某幾張表不一致的狀況下,能夠把這幾張道出來,恢復到從庫
如何修改了系統編碼了:
# centos 6.x 版本是/etc/sysconfig/i18n 修改這個文件 shell> vim /etc/sysconfig/i18n # 這一行改成utf8 LANG=en_US.UTF-8 # 修改完,不要重啓,當即生效以下 shell> source /etc/sysconfig/i18n # centos 7.x 版本是/etc/locale.conf 這個文件 [root@mysql-150 ~]# vim /etc/locale.conf LANG="en_US.UTF-8" #當即生效 [root@mysql-150 ~]# source /etc/locale.conf
在參數文件中的[mysqld] 下,加入相應utf8字符集
# 注意數據庫的系統版本 5.6.x 和 5.7.x設置字符集參數不同,8.x和5.7.x設置是同樣的 #查看當前數據庫的字符集參數,查看當前字符集參數 mysql> show variables like '%character%'; # 查看數據庫支持的字符編碼,和編碼的排序規則 mysql> show character set; # 修改sutdents表中sname 字段的字符編碼 mysql> alter table students modify sname varchar(66) character set gbk; Query OK, 3 rows affected (0.06 sec) Records: 3 Duplicates: 0 Warnings: 0 #看看錶結構 mysql> show create table students; ... | students | CREATE TABLE `students` ( `sid` int(11) NOT NULL, `sname` varchar(66) CHARACTER SET gbk DEFAULT NULL, `sex` int(11) DEFAULT NULL, PRIMARY KEY (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | ... # 查看鏈接級字符集和排序規則 mysql> show variables like '%collation%'; +----------------------+-----------------+ | Variable_name | Value | +----------------------+-----------------+ | collation_connection | utf8_general_ci | | collation_database | utf8_general_ci | | collation_server | utf8_general_ci | +----------------------+-----------------+
從上面示例能夠得出:
列級別字符集
表級別字符集
庫級別字符集
mysql 實例字符集
vim /etc/my.cnf [mysqld] init-connect='SET NAMES utf8' character-set-server=utf8 而後去數據庫操做: mysql> set @@global.character_set_server=utf8; Query OK, 0 rows affected (0.00 sec) mysql> set @@global.init_connect='SET NAMES utf8'; Query OK, 0 rows affected (0.00 sec) # 注 用戶操做的時候看看有沒有super權限,對super用戶權限 set names 不生效
有人說,修改完仍是亂碼, 這時候就亂碼是哪一個庫的字符集,哪一個表的字符集,哪一個字段的字符集,還有操做系統字符集,程序鏈接的字符集,這些都的查看。
好比:
# 舉例init_connect mysql> SET @@GLOBAL.init_connect='SET AUTOCOMMIT=0;set names utf8'; shell> vim my.cnf [mysqld] init_connect='SET AUTOCOMMIT=0;set names utf8'
每一個數據庫客戶端鏈接都有本身的字符集和排序規則屬性,
客戶端發送的語句的字符集是由character_set_client決定,
而與服務端交互時會根據character_set_connection和collation_connection兩個參數將接收到的語句轉化。當涉及到顯示字符串的比較時,由collation_connection參數決定,
character_set_result參數決定了語句的執行結果以什麼字符集返回給客戶端
客戶端能夠很方便的調整字符集和排序規則,好比使用SET NAMES 'charset_name' [COLLATE 'collation_name']代表後續的語句都以該字符集格式傳送給服務端,而執行結果也以此字符集格式返回。
set names 字符集
set names charset_name 語句至關於執行了如下三行語句: SET character_set_client = charset_name; SET character_set_results = charset_name; SET character_set_connection = charset_name;
SET character_set_client = charset_name; SET character_set_results = charset_name; SET character_set_connection = @@character_set_database;
數據庫從: 全局數據庫server字符集——>數據庫字符集——> 表字符集——> 列字符集
解決思路:
首先咱們要先查看數據庫的 error log。而後判斷是表損壞,仍是權限問題。還有可能磁盤空間不足致使的不能正常訪問表,操做系統的限制也要關注下,相關應用限制也要關注下;
#ulimit -n 查看系統的最大打開文件數 [root@mysql-150 ~]# ulimit -n 65535
查看數據庫的打開文件數
mysql> show variables like 'open_files_limit'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | open_files_limit | 5000 | +------------------+-------+ # 根據業務實際狀況修改打開文件數通常足夠用了,低版本的打開文件數,可能有點小, 注意一下
哪就是其餘的問題了,多是表的權限,也多是表出問題,根據錯誤日誌,具體分析
處理方法
repair table tablename
chown mysql.mysql 權限 目錄
清理磁盤中的垃圾數據
mysql 參數的問題,是否是參數配置的不合理,一直不釋放鏈接;
mysql 語句的問題,數據庫查詢不夠優化,過分耗時。
大併發狀況問題,致使 sleep 狀況過多;
不少人都是重啓大法,重啓大法確實好, 可以釋放,生產重啓對業務有影響的,不能隨便重啓的
shell腳本+cron計劃任務,來kill sleep 線程,這個不靠譜啊, 你不知道 sleep 線程,裏面是否是還有事務還在執行沒有提交,也是sleep 狀態,這個kill 操做有點莽夫,對生產數據數據庫仍是要理智啊。
我臨時解決的辦法:
修改 mysql 參數問題 ,修改wait_timeout
和interactive_timeout
默認都是28800秒有,也就是8個小時之後才釋放空連接。
例子:
不一樣用戶登陸到數據庫,wait_timeout和interactive_timeout
都是28800秒
修改參數,我生產環境設置的是半個小時,也就是1800秒
mysql> set global wait_timeout=1800; mysql> set global interactive_timeout=1800; shell> vim my.cnf [mysqld] wait_timeout=1800 interactive_timeout=1800
#開啓兩個會話窗口 mysql> # 從新登陸了會話,wait_timeout和interactive會生效 mysql> show variables like 'wait_timeout'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | wait_timeout | 1800 | +---------------+-------+ 1 row in set (0.00 sec) mysql> show variables like 'interactive_timeout'; +---------------------+-------+ | Variable_name | Value | +---------------------+-------+ | interactive_timeout | 1800 | +---------------------+-------+ 1 row in set (0.00 sec) #session2 mysql> #這個是其餘用戶鏈接的mysql,這個會話一直沒有斷開,參數仍是28800 mysql> show variables like 'wait_timeout'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | wait_timeout | 28800 | +---------------+-------+ 1 row in set (0.01 sec) mysql> show variables like 'interactive_timeout'; +---------------------+-------+ | Variable_name | Value | +---------------------+-------+ | interactive_timeout | 28800 | +---------------------+-------+ 1 row in set (0.00 sec)
這時候就要知道 形成 sleep 線程過多的緣由來解決:
程序執行完畢,應該顯式調用mysql_close
能逐步分析系統的SQL查詢,找到查詢過慢的SQL優化
合理設置mysql參數值