什么是事务的隔离级别&c++锁

94 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

隔离

像各大编程语言保证临界区数据安全用锁, 那么mysql具体用啥子保证数据安全?下面给予介绍哈哈

1.重点简述

介绍流程图1.1

graph TD
MySQL事务隔离级别的概念与序列化隔离 -->
MySQL事务隔离级别可重复读-提交读和未提交读 -->
MySQL性能与非事务表的表锁定
c++锁介绍--> 3个线程轮流输出A,B,C
c++锁介绍--> 保护临界区

MySQL事务隔离级别的概念与序列化隔离

查看隔离级别: SELECT @@GLOBAL.tx_isolation ,@@session.tx_isolation

设置隔离级别: set SESSION TRANSACTION ISOLATION LEVEL serializable(XXX)

四种隔离级别

  1. serializable:序列化(或串行化)
全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

就是对事务操作进行排队,一个事务能执行当且仅当它前面没有事务等待。

2 repeatable read: 可重复读

在同一个事务内的查询都是事务开始时刻一致的

就是在同一个事务里面先后执行同一个查询语句的时候,得到的结果是一样的

3 read committed: 提交读

只能读取到已经提交的数据

4 read uncommitted: 未提交读

允许脏读,也就是可能读取到其他会话中未提交事务修改的数据

并发情况下,读操作可能存在的三类问题:

  1. 脏读:当前事务(A)中可以读到其他事务(B)未提交的数据(脏数据),这种现象是脏读。
  2. 不可重复读:在事务A中先后两次读取同一个数据,两次读取的结果不一样,这种现象称为不可重复读。脏读与不可重复读的区别在于:前者读到的是其他事务未提交的数据,后者读到的是其他事务已提交的数据。
  3. 幻读:在事务A中按照某个条件先后两次查询数据库,两次查询结果的条数不同,这种现象称为幻读。不可重复读与幻读的区别可以通俗的理解为:前者是数据变了,后者是数据的行数变了。

场景

10个线程同时对一个数(num)进行加操作,保证num的安全性

参考实现

#include <thread>
#include <iostream>
#include<mutex>
int num = 0;
std::mutex mutex;

void plus(){
    std::lock_guard<std::mutex> guard(mutex);
    std::cout << num++ <<std::endl;
}

int main(){
    std::thread threads[10];
    for (auto & i : threads) {
        i = std::thread(plus);
    }
    for (auto & thread : threads) {
        thread.join();
    }
    return 0;
}

条件变量

场景

3个线程轮流输出A,B,C

参考实现

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

int num = 0;
std::mutex mutex;
std::condition_variable cv;
std::thread t[3];
std::string s = "abc";
void run(int id){
   for(int i=0;i<3;i++){
        std::unique_lock<std::mutex> lock(mutex);
        cv.wait(lock,[&]()->bool{
            return id==num;
        });
        num=(num+1)%3;
        std::cout<<s[id]<<" ";
        cv.notify_all();
    }
}
int main(){
    for(int i=0;i<3;i++){
        t[i]=std::thread(run,i);
    }
    for(int i=0;i<3;i++){
        t[i].join();
    }
    return 0;
}