Untuk keselamatan data, pangkalan data perlu disandarkan secara berkala menyebabkan data tidak konsisten. Brother Song memberikan contoh mudah Mari kita lihat contoh:
Katakan pengguna membuat pesanan semasa tempoh sandaran pangkalan data, maka masalah berikut mungkin berlaku:
Jadual inventori menolak inventori.
Sandarkan jadual inventori.
Sandarkan data jadual pesanan.
Tambah pesanan pada jadual pesanan.
Jadual pengguna menolak baki akaun.
Sandarkan jadual pengguna.
Jika anda mengikut logik di atas, jadual pesanan dalam fail sandaran akan kehilangan rekod. Jika anda menggunakan fail sandaran ini untuk memulihkan data, satu rekod akan hilang, menyebabkan data tidak konsisten.
Untuk menyelesaikan masalah ini, MySQL menyediakan banyak penyelesaian Mari kita jelaskan satu persatu dan menganalisis kelebihan dan kekurangannya.
Untuk menyelesaikan masalah ini, cara paling mudah yang boleh kita fikirkan ialah menetapkan pangkalan data untuk dibaca sahaja semasa sandaran pangkalan data dan tidak boleh ditulis. , supaya kita tidak perlu risau tentang ketidakkonsistenan data Kaedah menetapkan keseluruhan pangkalan data untuk dibaca sahaja juga sangat mudah, pertama, kita melaksanakan SQL berikut dan melihat nilai pembolehubah yang sepadan:
show variables like 'read_only';
Seperti yang anda lihat, secara lalai, read_only
DIMATIKAN, iaitu keadaan tertutup Kami mula-mula menukarnya kepada HIDUP dan laksanakan SQL berikut:
1 bermaksud HIDUP, 0 bermakna MATI Keputusan pelaksanaan adalah seperti berikut:
Iniread_only
tidak sah untuk pengguna super, jadi selepas tetapan adalah selesai, kami keluar dari sesi ini, kemudian buat pengguna tanpa kebenaran super, log masuk dengan pengguna baharu, dan selepas log masuk berjaya, laksanakan SQL sisipan, Hasilnya adalah seperti berikut:
Seperti yang anda lihat, mesej ralat ini mengatakan bahawa MySQL semasa adalah baca sahaja (hanya boleh membuat pertanyaan) dan tidak boleh melaksanakan SQL semasa.
Dengan ditambahkan atribut baca sahaja, anda tidak perlu risau tentang ketidakkonsistenan data semasa sandaran.
Tetapi read_only
kami biasanya menggunakannya untuk mengenal pasti sama ada tika MySQL ialah perpustakaan induk atau perpustakaan hamba:
read_only=0, menunjukkan bahawa tika itu ialah perpustakaan induk. Pentadbir pangkalan data DBA boleh menulis beberapa data bukan perniagaan kepada contoh sekali-sekala untuk menentukan sama ada pustaka utama boleh ditulis dan tersedia Ini adalah cara biasa untuk mengesan sama ada tika perpustakaan utama masih hidup.
read_only=1, menunjukkan bahawa tika itu ialah perpustakaan hamba. Biasanya, apabila kerap meneroka perpustakaan hamba, hanya beberapa operasi baca akan dilakukan, seperti pernyataan seperti "pilih 1;".
Jadi, read_only
atribut ini sebenarnya tidak sesuai untuk sandaran, dan jika anda menggunakan atribut read_only
untuk menetapkan keseluruhan perpustakaan kepada baca sahaja, jika pengecualian berlaku pada klien , Kemudian pangkalan data akan sentiasa kekal dalam keadaan baca sahaja, yang akan menyebabkan keseluruhan perpustakaan berada dalam keadaan tidak boleh ditulis untuk masa yang lama, dan risikonya sangat tinggi.
Oleh itu penyelesaian ini tidak layak.
Kunci global, seperti namanya, mengunci seluruh perpustakaan yang dikunci tidak boleh ditambah, dipadam atau diubah suai, hanya dibaca.
Kemudian mari kita lihat cara menggunakan kunci global. MySQL menyediakan kaedah untuk meningkatkan kunci baca global, arahannya ialah flush tables with read lock
(FTWRL). Apabila anda perlu membuat keseluruhan pustaka dalam keadaan baca sahaja, anda boleh menggunakan arahan ini, dan kemudian operasi seperti penambahan, pemadaman dan pengubahsuaian oleh urutan lain akan disekat.
Seperti yang anda lihat daripada gambar, jadual boleh dikunci menggunakan perintah flush tables with read lock;
; operasi buka kunci boleh diselesaikan menggunakan perintah unlock tables;
(ia akan juga dibuka secara automatik apabila sesi diputuskan sambungan) ).
Berbanding dengan penyelesaian dalam bahagian pertama, FTWRL telah membuat beberapa kemajuan, iaitu: jika pelanggan memutuskan sambungan secara tidak normal selepas melaksanakan arahan FTWRL, MySQL akan secara automatik melepaskan kunci global, dan keseluruhan perpustakaan boleh dikemas kini secara normal dan bukannya kekal dalam status baca sahaja.
Tetapi! ! !
Menambah kunci global bermakna keseluruhan pangkalan data berada dalam keadaan baca sahaja semasa tempoh sandaran, jadi perniagaan hanya boleh ditutup semasa tempoh sandaran pangkalan data.
Jadi kaedah ini bukanlah penyelesaian terbaik.
Saya tidak tahu sama ada anda masih ingat tahap pengasingan pangkalan data yang Brother Song kongsi dengan anda sebelum ini. yang juga MySQL Tahap pengasingan lalai. 可重复读(REPEATABLE READ)
换言之,在 InnoDB 这种支持事务的存储引擎中,那么我们就可以在备份数据库之前先开启事务,此时会先创建一致性视图,然后整个事务执行期间都在用这个一致性视图,而且由于 MVCC 的支持,备份期间业务依然可以对数据进行更新操作,并且这些更新操作不会被当前事务看到。
在可重复读的隔离级别下,即使其他事务更新了表数据,也不会影响备份数据库的事务读取结果,这就是事务四大特性中的隔离性,这样备份期间备份的数据一直是在开启事务时的数据。
具体操作也很简单,使用 mysqldump 备份数据库的时候,加上 -–single-transaction
参数即可。
为了看到 -–single-transaction
参数的作用,我们可以先开启 general_log
,general_log
即 General Query Log,它记录了 MySQL 服务器的操作。当客户端连接、断开连接、接收到客户端的 SQL 语句时,会向 general_log
中写入日志,开启 general_log
会损失一定的性能,但是在开发、测试环境下开启日志,可以帮忙我们加快排查出现的问题。
通过如下查询我们可以看到,默认情况下 general_log
并没有开启:
我们可以通过修改配置文件 my.cnf(Linux)/my.ini(Windows)
,在 mysqld
下面增加或修改(如已存在配置项)general_log
的值为1,修改后重启 MySQL 服务即可生效。
也可以通过在 MySQL 终端执行 set global general_log = ON
来开启 general log
,此方法可以不用重启 MySQL
。
开启之后,默认日志的目录是 mysql 的 data 目录,文件名默认为 主机名.log
。
接下来,我们先来执行一个不带 -–single-transaction
参数的备份,如下:
mysqldump -h localhost -uroot -p123 test08 > test08.sql
大家注意默认的 general_log
的位置。
接下来我们再来加上 -–single-transaction
参数看看:
mysqldump -h localhost -uroot -p123 --single-transaction test08 > test08.sql
大家看我蓝色选中的部分,可以看到,确实先开启了事务,然后才开始备份的,对比不加 -–single-transaction
参数的日志,多了开启事务这一部分。
Atas ialah kandungan terperinci Bagaimanakah MySQL memastikan konsistensi data sandaran?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!