mysql 同时访问_mysql多线程访问

本文讨论了在多线程环境中如何安全地使用MySQL C API,包括线程安全连接、并发控制和最佳操作实践。在多线程访问MySQL时,需要注意在mysql_query()和mysql_store_result()之间确保只有一个线程操作,并使用线程锁进行同步。此外,还提到了开启事务前的清理、处理重连逻辑、避免二进制数据问题、检查受影响行数、设置连接超时、正确释放资源、使用合适的隔离级别、避免锁间隙问题等多方面的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.blogbus.com/skatings-logs/48527211.html

如果你用线程的编程,你应该用--with-thread-safe-client编译MySQL C API,这将使C API线程对每个连接更安全。你可以让2个线程共享相同的连接,只要如果你做下列事情:

两个线程不能同时在同一个连接上发送查询到MySQL。特别是你必须保证在一个mysql_query()和mysql_store_result()之间没有其他线程正在使用同一个连接。

许多线程能存取用mysql_store_result()检索出来的不同结果集合。

如果你使用mysql_use_result,你必须保证没有其他线程在同一个连接上正在询问任何东西,直到结果集合被关闭。

设计如下线程,验证上述内容, Thread1和Thread2使用同一个mysql连接,执行select语句:

Thread1: Thread2:

mysql_query();              sleep(1);

| |

| |

sleep(2); mysql_query();

| |

| |

mysql_store_result(); mysql_store_result();

线程2中调用mysql_query()时出错,通过mysql_error()返回的错误信息为:Commands out of sync; you can’t run this command now.

解决方法1:

一个线程分配一个mysql连接

解决方法2:

在mysql_query()之前加上线程锁,在mysql_store_result()之后释放线程锁,

pthread_mutex_lock();

|

|

mysql_query();

|

|

mysql_store_result();

|

|

pthread_mutex_unlock();

不得以要用多线程,大概确定要注意这些:

(1)使mysql_real_connect()线程安全。(再次编译:shell> ./configure --enable-thread-safe-client)

-------------------------------------

(2)一个连接上,要确保在mysql_query()和mysql_store_result()之间,只有一个线程。

(大多Mysql数据库封装类库顾不到多线程,别用任何类库)

------------------------------------

请指导,还有哪些要注意的,譬如,要改成INNODB的结构吗?

---------------问题补充---------------

@jsyang888: http://www.oschina.net/p/transfer (Mysql-transfer 多线程) 这有人用过吗 ?(2年前)

http://blog.youkuaiyun.com/wenzi49312/article/details/8537727

1 开启事务之前需要rollback 连接句柄。(清理垃圾)

2 mysql_ping 失败,程序需要处理重连逻辑;

3 mysql_query()执行的SQL语句是一个以‘/0’结尾的字符串,而mysql_real_query()执行的字符串长度是参数指定的,因此,前者不能不能包含二进制数据(二进制数据中可能会包含‘/0’,导致被认为到达字符串末尾)

实际使用中,推荐使用mysql_real_query

4 mysql C API   中SQL不需要 ';' 结尾;

5 mysql 转义;(老问题了)

6 所有update 语句,建议后边调用函数判断受影响的行数,是否是自己预期值;

7 mysql_real_connect 需要设置连接超时时间,特别是处理重连逻辑的时候,以免程序堵死;

8 程序rollback时候, 需要习惯性的校验应用的错误码,避免错误码没有赋值,调用者以为调用成功,造成漏洞;

9 多线程环境下使用libmysqlclient_r 库,非libmysqlclient 库

10 mysql_real_connect/mysql_init 多线程环境下调用需要加锁;

11 使用mysql_real_escape_string, 需要注意目标缓冲区是 2*n+1 大小;

12 mysql_store_result 这个函数是分配的内存的。 使用完需要释放,避免内存泄露;

13 mysql的事务尽量小,使用完,立即commit或rollback.不要起一个过大的事务。

14 mysql的隔离级别注意使用 Read Commited。不然会产生锁间隙的问题。

15 避免尝试去锁一个不存在的记录,for update语句where条件请使用主键(锁定一个非主键,会默认同时锁定一个主键,这是造成很多死锁的原因)。避免过多的for update。

16 select语句必须使用索引,where条件避免使用 or 或者在条件中运用运算表达式,会造成索引失效。

17 联合索引可以替代单独的索引。如果已有联合索引,不需要重复建立单独的索引。索引过多会导致插入变慢。注意是联合索引的第一个可以省略。 避过(f1,f2),可以省略f1的单独索引,但是不能省略f2的单独索引。

18 where条件,结果集不要太大,如果超过30%,索引会时效,会导致mysql扫描全表。不确定时,请用explain做检测。

19 mysql单表记录保持在1000W以下,以获得较好的性能。

20 mysql数据库链接数不能过多,请保持在200以下。

21 修改mysql 锁等待时间,默认为50s,避免for update等待时间超长,造成系统阻塞 innodb_lock_wait_timeout(修改这个属性需要重启数据库)

22 如果启用事务,可以不必显示的设置set autocommit=0,即使当时autocommit模式为1(直接提交模式),可以通过begin/commit来隐式的调用。

如果不使用事务,则必须显示的调用 set autocommit=1.因为不能确定,是否某长链接中,有人设置了set autocommit=0.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值