golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发


多用户访问会遇到问题,同时访问一个数据,修改,到底哪个用户说了算

myisam存储引擎是表级锁,innodb行级锁,mvcc机制(多版本并发控制,也可以在一定程度上提高并发访问,同时对数据库记录进行修改)

读锁只能,读不能写,(做备份的时候,备份是基于时间点的数据,备份完了才能进行修改)
写锁,独占锁,将只能自己访问数据,别人不能读

golang mysql单服务器并发 mysql单机并发_数据库_02


存储引擎会自动加锁,也可以服务器自己用户加锁

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_03

golang mysql单服务器并发 mysql单机并发_数据_04

read读锁,只读不可写,write,排他锁,你在访问,其他人就访问不了

golang mysql单服务器并发 mysql单机并发_数据_05


前面创建了表,立即加了一个写锁,加完数据再释放锁

golang mysql单服务器并发 mysql单机并发_数据_06


表和表有关系这样就会存在一些问题,将来写代码需要考虑

golang mysql单服务器并发 mysql单机并发_数据库_07

golang mysql单服务器并发 mysql单机并发_数据_08


开两个终端连接数据库

golang mysql单服务器并发 mysql单机并发_数据库_09


重新导入数据

golang mysql单服务器并发 mysql单机并发_数据_10


golang mysql单服务器并发 mysql单机并发_隔离级别_11


当前tearcher表加了个读锁,不能加入数据

golang mysql单服务器并发 mysql单机并发_数据_12


别的终端插入会一直等你释放,本终端会提示拒绝

golang mysql单服务器并发 mysql单机并发_数据库_13


解锁 unlock tables

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_14


另外终端就立即更新成功

golang mysql单服务器并发 mysql单机并发_数据_15


写锁意味排他,但是自己能读能写

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_16


别的终端就无法读

golang mysql单服务器并发 mysql单机并发_数据库_17

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_18


释放之后就马上可以读了

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_19


再次加锁

golang mysql单服务器并发 mysql单机并发_隔离级别_20


另外终端再查就会去缓存里查了,不会拒绝你通过缓存查询的

golang mysql单服务器并发 mysql单机并发_隔离级别_21


可以设置不允许使用查询缓存,默认OFF,即时加锁,也允许从缓存得到数据

golang mysql单服务器并发 mysql单机并发_数据库_22

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_23


退出重新登录

golang mysql单服务器并发 mysql单机并发_隔离级别_24


再加上写锁

golang mysql单服务器并发 mysql单机并发_隔离级别_25


其他终端就不让查了

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_26


unlock tables解锁

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_27


查几次,应该有缓存了

golang mysql单服务器并发 mysql单机并发_隔离级别_28


再次枷锁

golang mysql单服务器并发 mysql单机并发_数据_29


加了锁就不行了

golang mysql单服务器并发 mysql单机并发_隔离级别_30

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_31

结合锁就涉及到事务并发的问题
ACID特性

golang mysql单服务器并发 mysql单机并发_数据库_32

对数据库的数据进行修改,第一步先放到内存,100,100修改成200,第二部先把更改写到日志里,update 100=200,第三步吧数据库更改写到磁盘里

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_33


假如现在有三条不同操作,三条事务都做完了才会提交,数据库完成更改

golang mysql单服务器并发 mysql单机并发_隔离级别_34

这时候内存数据丢了,只有第一步第二步完成了,事务不完整,吧刚才做过的事务日志撤销,就是rollback回滚或者undo撤销

golang mysql单服务器并发 mysql单机并发_数据_35

可能还有另外一种情况,有多个事务,之前的事务结束了,是一个完整的事务,但是不一定事务结束了,就立即把数据写到磁盘里
因为什么时候写是根据系统是否空闲来决定的,
做到45的时候系统停电了,就会发现45这个事务出现问题,就把这个从事务日志中撤销,前面123做完了,是一个完整的事务,就会在磁盘上执行,redo操作。
保证事务完成的,数据库就留得住

golang mysql单服务器并发 mysql单机并发_隔离级别_36


数据库始终存一致状态,比如银行转账

golang mysql单服务器并发 mysql单机并发_隔离级别_37


事务没结束,没改完的数据叫脏数据,需要隔离的,希望别人不要看到

golang mysql单服务器并发 mysql单机并发_隔离级别_38


事务提交,就是永久保存在数据库,无法后悔

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_39

golang mysql单服务器并发 mysql单机并发_数据_40

**,初始化数据库 initial db state

开始一个事务 start transaction

增删改,查询不算一个事务部分,只有增删改才会记录在事务日志里

commit提交 数据库状态就发生变化

rollback 回滚

**

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_41

通常有两种事务,一种是显性事务 手动提交,一种是隐性事务 自动提交
mysql默认隐性事务,默认执行增删改就commit
oracle默认不会自动提交,必须明确写commit才能提交

golang mysql单服务器并发 mysql单机并发_隔离级别_42


@@两个代表系统变量,@一个代表自定义变量

golang mysql单服务器并发 mysql单机并发_数据库_43


默认autocommit=1,只要进行修改马上就提交

golang mysql单服务器并发 mysql单机并发_数据库_44


可以修改成非自动提交

golang mysql单服务器并发 mysql单机并发_数据库_45


自己添加数据是可以看到的

golang mysql单服务器并发 mysql单机并发_隔离级别_46


另外终端看不到,因为是脏数据

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_47


现在可以撤销

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_48


如果要多个语句执行,想提高效率,最后再commit

golang mysql单服务器并发 mysql单机并发_数据库_49


开启事务了,只要不commit就不会提交事务

golang mysql单服务器并发 mysql单机并发_数据库_50

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_51


rollback撤销,8,9行就没了

golang mysql单服务器并发 mysql单机并发_隔离级别_52

golang mysql单服务器并发 mysql单机并发_隔离级别_53


现在rollback没有用了,已经自动提交了

golang mysql单服务器并发 mysql单机并发_数据库_54


现在清空表

golang mysql单服务器并发 mysql单机并发_隔离级别_55


开启事务,速度很快,事务不仅保证安全,效率比一条条commit来的速度快

golang mysql单服务器并发 mysql单机并发_隔离级别_56


事务还可以部分撤销

golang mysql单服务器并发 mysql单机并发_数据_57


在事务的执行的时候,还有个保存事务执行节点,
可以在执行事务的时候 ,定义一个位置,带来的好处就是,可以在标签的地方,选择性的撤销
如果没有标签,之前rollback是全部都撤销了

golang mysql单服务器并发 mysql单机并发_数据库_58

事务的隔离级别严重的影响了多个事务并发访问数据库的表现
隔离级别分成4个:
read uncommitted 读到未提交的数据,t1事务还未结束,t2就能看到了,脏数据

golang mysql单服务器并发 mysql单机并发_隔离级别_59


READ COMMITED 不可重复读,能查看提交的数据,未提交的看不到,叫不可重复读, 因为多个事务再修改的时候,导致你每次看到的数据都不一样
每次读取的数据都不一样

golang mysql单服务器并发 mysql单机并发_数据库_60


REPEATABLE READ 可重复读,就有要求,至少在你这个事务里看到的数据是一样的,就有可重复读,保证一个事务里,数据是一致的

golang mysql单服务器并发 mysql单机并发_数据库_61


也就是实际数据发生改变,但是在B事务的生命期里看到的还是以前的,造成幻读,自我欺骗,这样可以执行备份命令,在备份期间,别人持续修改数据,无所谓,对并发是没什么影响的

golang mysql单服务器并发 mysql单机并发_数据库_62


SERIALIZABILE,未提交的读事务将阻塞另外一个修改事务,就不会造成之前的问题,数据是最稳定的但是并发性能差

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_63

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_64

设置事务的隔离级别

golang mysql单服务器并发 mysql单机并发_数据库_65


tx_isloatinotallow=事务的隔离级别来设置目前的状态是重复读

golang mysql单服务器并发 mysql单机并发_数据_66

修改成不可重复读,这样不是可以永久保存的

golang mysql单服务器并发 mysql单机并发_数据库_67


永久保存,写到配置文件里

golang mysql单服务器并发 mysql单机并发_数据_68


golang mysql单服务器并发 mysql单机并发_隔离级别_69


是个变量不是服务器选项,不能写到配置文件里

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_70


要写成这样

golang mysql单服务器并发 mysql单机并发_数据库_71


golang mysql单服务器并发 mysql单机并发_数据库_72


golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_73


开启一个事务

golang mysql单服务器并发 mysql单机并发_数据库_74


另外的终端是可以看到的,因为隔离级别的read-uncommited,(可以看到脏数据)

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_75


撤销了

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_76


另外的终端再次查看就没了

golang mysql单服务器并发 mysql单机并发_数据库_77


还可以改成另外的隔离级别,READ-COMMITED,不可重复读

golang mysql单服务器并发 mysql单机并发_数据库_78


开启事务,增加数据

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_79


另外的终端也开启事务

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_80


提交修改的

golang mysql单服务器并发 mysql单机并发_数据_81


另外的终端可以看到提交的,也就是在同一个事务期间看到的数据可能不一样

golang mysql单服务器并发 mysql单机并发_隔离级别_82


注释掉,默认隔离级别是可重复读, REPEATABLE-READ

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_83

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_84


另外终端看到的仍然是8条

golang mysql单服务器并发 mysql单机并发_数据_85


另外的终端开启一个事务

golang mysql单服务器并发 mysql单机并发_隔离级别_86


提交

golang mysql单服务器并发 mysql单机并发_隔离级别_87


另外的终端还是看到8个,系统默认的可重复读

golang mysql单服务器并发 mysql单机并发_数据_88


事务提交了就能看到别人改的数据了

golang mysql单服务器并发 mysql单机并发_数据库_89

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_63

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_91


两个终端都开启事务

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_92


golang mysql单服务器并发 mysql单机并发_数据库_93

golang mysql单服务器并发 mysql单机并发_数据_94


一个事务开启了读,另外的就改不了

golang mysql单服务器并发 mysql单机并发_数据库_95


事务的未提交读会阻塞写

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_96

golang mysql单服务器并发 mysql单机并发_数据_97


就成功了

golang mysql单服务器并发 mysql单机并发_数据_98


再次开启一个事务

golang mysql单服务器并发 mysql单机并发_数据库_99


不让查,因为另外一遍的写操作没提交

golang mysql单服务器并发 mysql单机并发_数据_100


未提交的写操作阻塞读事务删除可以后悔,rollback

golang mysql单服务器并发 mysql单机并发_数据库_101


**撤销不是万能的,只能针对增删改,DDL语言撤销不来,数据库的定义语言(创建表,修改表,删除表),trancate ,drop撤销不来

撤销的是DML(增删改) **

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_102

golang mysql单服务器并发 mysql单机并发_数据_103


MVCC是在每个表加两个字段,create,delete,确保事务一致性,在READ UNCOMMITED是不起作用的,可以看到脏数据,串行化也是不起作用的

golang mysql单服务器并发 mysql单机并发_数据库_104


golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_105


串行化,会加锁,锁住这个资源,不让别人访问

golang mysql单服务器并发 mysql单机并发_隔离级别_106


另外的终端开启事务,是看到没有改的数据

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_107


同时修改数据

golang mysql单服务器并发 mysql单机并发_隔离级别_108


换成另外一条记录就可以修改

golang mysql单服务器并发 mysql单机并发_数据库_109


innodb是行级锁,如果两个改,一个人改了一般,离开了,但是没提交,导致一直锁着,别人无法修改

golang mysql单服务器并发 mysql单机并发_数据库_110


有个超时时长

golang mysql单服务器并发 mysql单机并发_数据_111


可以把进程2删除,因为这是另外一个终端修改的进程

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_112


另外的终端就成功了,刚才的直接杀掉进程了

golang mysql单服务器并发 mysql单机并发_数据库_113


被踢出来了

golang mysql单服务器并发 mysql单机并发_golang mysql单服务器并发_114


通讯双方多个事务执行,出现死锁,就需要避免