【MySQL】binlog緩存的問題和性能


之前在沒有備庫的情況下,遇到過more than 'max_binlog_cache_size' bytes of storage 的錯誤,今天在主備復制的時候又遇到了這個問題

Last_SQL_Errno: 1197
Last_SQL_Error: Worker 14 failed executing transaction '' at master log mysql-bin.050101, end_log_pos 2669492980; Could not execute Delete_rows_v1 event on table time_dispatcher_0029.ttd_task_1889; Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again, Error_code: 1197; handler error HA_ERR_RBR_LOGGING_FAILED; the event's master log mysql-bin.050101, end_log_pos 2669492980

slave

root@(none) 10:11:38>show variables like '%binlog_%size%';
+----------------------------+----------------------+
| Variable_name              | Value                |
+----------------------------+----------------------+
| binlog_cache_size          | 32768                |
| binlog_stmt_cache_size     | 32768                |
| max_binlog_cache_size      | 2147483648           |
| max_binlog_size            | 524288000            |
| max_binlog_stmt_cache_size | 18446744073709547520 |
+----------------------------+----------------------+
root@(none) 09:51:00>show status like 'binlog_%';   
+----------------------------+-----------+
| Variable_name              | Value     |
+----------------------------+-----------+
| Binlog_cache_disk_use      | 86332     |
| Binlog_cache_use           | 320562298 |
| Binlog_stmt_cache_disk_use | 0         |
| Binlog_stmt_cache_use      | 145       |
+----------------------------+-----------+

master

root@(none) 10:07:17>show variables like '%binlog_cache_size%';
+-----------------------+-------------+
| Variable_name         | Value       |
+-----------------------+-------------+
| binlog_cache_size     | 32768       |
| max_binlog_cache_size | 10737418240 |
+-----------------------+-------------+

主備設置不一致導致主庫寫binlog成功,備庫在恢復relog的時候同樣記錄binlog,但是主備cache大小設置不同,所以導致了上邊的問題。

主備參數的一致性很重要!!!!

修復

root@(none) 10:08:49>stop slave;
Query OK, 0 rows affected, 1 warning (0.02 sec)
root@(none) 10:08:32>set global max_binlog_cache_size=10737418240;         
Query OK, 0 rows affected (0.00 sec)
root@(none) 10:08:49>start slave;
Query OK, 0 rows affected, 1 warning (0.02 sec)

max_binlog_cache_size

如果事務需要內存超過此字節數,服務器生成如下錯誤ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage;max_binlog_cache_size最低值是4096,最大可能值為16EB(艾字節)。推薦的最大值為4GB ;因為目前的MySQL當二進制日志位置大於4GB時並不生效。

Note:

Prior to MySQL 5.6.7, 64-bit Windows platforms truncated the stored value for this variable to 4G, even when it was set to a greater value (Bug #13961678).

在MySQL 5.6 ,會話對於max_binlog_cache_size的感知依賴於binlog_cache_size系統變量;換句話說,改變其值只會影響后續新建會話。

max_binlog_size

如果寫二進制日志導致當前日志文件大小超過了這個變量的值時,服務器旋轉二進制日志(關閉當前的文件,並打開下一個) 。的最小值為4096字節。最大值和默認值是1GB 。

事務是以塊為單位寫入二進制日志的,因此它不會被拆分在幾個二進制日志。如果你有大的交易,你可能會看到比max_binlog_size較大的二進制日志文件。

如果max_relay_log_size為0,max_binlog_size的值會被應用到中繼日志。

max_binlog_stmt_cache_size

如果一個事務中的非事務性的語句需要大於這個數量的更多的內存,服務器會產生報錯。最低值是4096 ,在32位平台最大和默認值是4GB。在64位平台最大和默認值是416EB(艾字節)。

Note

Prior to MySQL 5.6.7, 64-bit Windows platforms truncated the stored value for this variable to 4G, even when it was set to a greater value (Bug #13961678).

max_binlog_cache_size針對事務語句,max_binlog_stmt_cache_size針對非事務語句,當我們發現Binlog_cache_disk_use或者Binlog_stmt_cache_disk_use比較大時就需要考慮增大cache的大小

事務性語句&非事務性語句

在事務性語句執行過程中,服務器將會進行額外的處理,在服務器執行時多個事務是並行執行的,為了把他們的記錄在一起,需要引入事務緩存的概念。在事務完成被提交的時候一同刷新到二進制日志。 對於非事務性語句的處理。遵循以下3條規則:

  1. 如果非事務性語句被標記為事務性,那么將被寫入事務緩沖。
  2. 如果沒有標記為事務性語句,而且事務緩存中沒有,那么直接寫入二進制日志。
  3. 如果沒有標記為事務性語句,但是事務緩存中有,那么寫入事務緩沖。

注意如果在一個事務中有非事務性語句,那么將會利用規則2,優先將該影響非事務表語句直接寫入二進制日志。

如果一切正常,當事務中執行事務語句(DML)的時候,所以這些語句形成的event都會被記錄到緩存里面,等到commit事務以后,這個緩存的數據會立即被刷入磁盤上的binlog文件里面,之后通過slave請求發送到slave,在slave重復執行。

順便提一下,mysql的binlog里面的事務都是相互獨立按順序排列的。

現在開始假設意外的發生。

正常意外一:事務執行中rollback了。

如果在一個事務中,所有執行的語句都是在innodb表上執行(對於多個事務引擎如tokudb等並用尚未測試),直接執行rollback,會導致mysql直接清除緩存,不會寫入任何event記錄到binlog。

正常意外二:事務執行中使用了非事務表(myisam),然后rollback了。

在一個事務中,即有事務表,也有非事務表,如果正常執行,則沒有任何問題,當如果在非事務表上的修改執行了,復制設置為statement的時候,binlog會把所有執行的event全部記錄下來寫入日志,包括事務與非事務語句,然后在最后面加上rollback。如果復制格式設置為row,那么所有事務表相關的數據都會被清理掉,而非事務表上的數據會被標記為已提交事務寫入binlog。

正常意外三:事務執行順序如下:事務語句1-》非事務語句2-》save point -》事務語句3 -》 rollback to savepoint -》 事務語句4 -》提交

對於上面的情況,statement情況下,所有執行的語句包括savepoint與rollback都會按順序被記錄到binlog。row情況下,非事務語句與事務語句是分別記錄到binlog中,非事務執行event會全部被記錄,事務執行event會連帶savepoint與rollback都記錄下來。

正常意外四:事務執行順序如下:事務語句1-》savepoint-》非事務語句2-》事務語句3-》rollback to savepoint-》事務語句4 -》 commit

同上。

異常意外一:master正常提交了,但是在slave執行失敗了。

master執行完成,提交之后,slave接收到relay然后執行,執行期間由於意外原因失敗了。這個時候,statement格式下,mysql會重新回到事務begin處重新執行,如果再次失敗的話就會報錯。row模式下情況類似,區別在於,如果是包含非事務表執行的事務,非事務表上的event不會被重新執行。

參考

Binary Log Options and Variables

max_binlog_stmt_cache_size

mysql復制對事務的處理

mysql二進制日志處理事務與非事務性語句的區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM