• mysql 数据库链接状态确认实验


    1.起因:

    在做一个小系统的时候,我想数据量交互不大,就都用一个链接执行算了,还能节省点资源,但是实际情况遇到了如下问题,在使用的过程中,有些数据操作会被转移到其他线程,这样;我这个简单的想法遇到了问题,因为一个现场在使用这个链接的时候,其他线程也会同步插入执行数据操作,这样一个链接就会面临共用的冲突,怎么办呢,有如下三种方案:

    1.1.数据两次一次一联,一用,一释放。

    1.2.强制是数据库的执行放到一个现场,那么得把所有的执行参数放到队列中,有数据支持的线程按照队列的顺序执行。也可以在使用的时候把链接索起来。这样强制的使数据的处理串行。

    1.3.做一个内部的链接对象使用池,池中的对象可供服用,解决重复链接的问题,提供多个对象解决现场使用冲突的问题。

    我选择了方案三,做了如下实验,记录如下

    2.实验

    2.1 确认数据链接状态,使用完的数据链接是什么状态呢?

    2.1.1 目的:我想根据链接的状态判断链接是在使用中,还是可以给别人使用;就是在可以使用的情况下,我就用该链接执行,否则使用或者创建其他的链接。

    代码。

    1. using System;
    2. using System.Data;
    3. namespace 数据库链接状态确认
    4. {
    5. /// <summary>
    6. /// 确认数据库通常执行完成是什么状态
    7. /// </summary>
    8. public class Test1:Singleton<Test1>
    9. {
    10. public void main()
    11. {
    12. test1();
    13. }
    14. private void test1()
    15. {
    16. DBmsqlSub dBmsqlSub = new DBmsqlSub();
    17. string sql = "insert into tb1(v1) values(2)";
    18. dBmsqlSub.ExecuteNonQuery(sql);
    19. ConnectionState connectionState = dBmsqlSub.getState();
    20. Console.WriteLine(connectionState);
    21. dBmsqlSub.Close();
    22. }
    23. }
    24. }

    结果,整理使用后的链接状态是open,那是不是open的时候就可以供别人使用了呢,要是在执行的时候也是open状态,那我就没有判定已经了。

    1. 数据库链接状态确认
    2. id0
    3. index:1 isuser:False setuser:False
    4. Open

    2.2 数据库在执行的时候,是不是有一个执行中的状态呢?

    代码

    1. using System;
    2. using System.Threading.Tasks;
    3. namespace 数据库链接状态确认
    4. {
    5. /// <summary>
    6. /// 目的:确认执行中的数据状态
    7. /// </summary>
    8. class Test2:Singleton<Test2>
    9. {
    10. public void main() {
    11. DBmsqlSub dBmsqlSub = new DBmsqlSub();
    12. Task.Factory.StartNew(test2Exe, (Object)dBmsqlSub);
    13. Task.Factory.StartNew(test2Exe, (Object)dBmsqlSub);
    14. Task.Factory.StartNew(test2State, dBmsqlSub);
    15. }
    16. private void test2Exe(object dBmsqlSub)
    17. {
    18. int index = 1;
    19. while (true)
    20. {
    21. index++;
    22. string sql = "insert into tb1(v1) values(" + index + ")";
    23. ((DBmsqlSub)dBmsqlSub).ExecuteNonQuery(sql);
    24. Task.Delay(200);
    25. }
    26. }
    27. private void test2State(object dBmsqlSub)
    28. {
    29. while (true)
    30. {
    31. Console.WriteLine(((DBmsqlSub)dBmsqlSub).getState());
    32. }
    33. }
    34. }
    35. }

    行结果执:即使执行中,对象的链接状态依然是open,那么用链接状态作为链接是否可用的计划泡汤了,那就只能用自添加的对象来控制链接是否可用了。

    1. Open
    2. Open
    3. Open
    4. Open
    5. id0
    6. Open
    7. Open
    8. Open
    9. Open
    10. Open
    11. Open

    2.3 测试3:添加对象的状态,控制链接是否可用

    2.3.1 代码

    1. using MySqlConnector;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5. using System.Text;
    6. using System.Threading.Tasks;
    7. namespace 数据库链接状态确认
    8. {
    9. class Test3:Singleton<Test3>
    10. {
    11. public void main() {
    12. test1();
    13. //test1();
    14. }
    15. private void test1() {
    16. Task.Factory.StartNew(test2Exe);
    17. Task.Factory.StartNew(test2Exe);
    18. Task.Factory.StartNew(test2Exe);
    19. }
    20. private void test2Exe()
    21. {
    22. int index = 1;
    23. while (true)
    24. {
    25. index++;
    26. string sql = "insert into tb1(v1) values(" + index + ")";
    27. DBmsql.getMy().ExecuteNonQuery(sql);
    28. }
    29. }
    30. private object MySqlDataReader(DBmsqlSub dBmsqlSub)
    31. {
    32. throw new NotImplementedException();
    33. }
    34. private void test2State(object dBmsqlSub)
    35. {
    36. while (true)
    37. {
    38. Console.WriteLine(((DBmsqlSub)dBmsqlSub).getState());
    39. }
    40. }
    41. }
    42. }

    2.3.2

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. namespace 数据库链接状态确认
    7. {
    8. class DBmsql : Singleton<DBmsql>
    9. {
    10. List<DBmsqlSub> dBmsqlSubs = new List<DBmsqlSub>();
    11. /// <summary>
    12. /// 执行sql命令
    13. /// </summary>
    14. /// <param name="CommandText"></param>
    15. public void ExecuteNonQuery(String CommandText)
    16. {
    17. getDBmsqlSub().ExecuteNonQuery(CommandText);
    18. }
    19. /// <summary>
    20. /// 插入数据,并返回插入数据的id
    21. /// </summary>
    22. /// <param name="CommandText"></param>
    23. /// <returns></returns>
    24. public int insertReturn(string CommandText)
    25. {
    26. int ret = getDBmsqlSub().insertReturn(CommandText);
    27. return ret;
    28. }
    29. /// <summary>
    30. /// 执行并返回一个对象
    31. /// </summary>
    32. /// <param name="CommandText"></param>
    33. /// <returns></returns>
    34. public object ExecuteScalar(string CommandText)
    35. {
    36. object o = getDBmsqlSub().ExecuteScalar(CommandText);
    37. return o;
    38. }
    39. /// <summary>
    40. /// 获取数据处理对象
    41. /// </summary>
    42. /// <returns></returns>
    43. private DBmsqlSub getDBmsqlSub()
    44. {
    45. DBmsqlSub ret = null;
    46. lock (dBmsqlSubs)
    47. {
    48. //避免两个同时取到允许的状态
    49. foreach (DBmsqlSub dBmsqlSub in dBmsqlSubs)
    50. {
    51. if (!dBmsqlSub.IsUrse())
    52. {
    53. ret = dBmsqlSub;
    54. dBmsqlSub.setIsUser(true);
    55. Console.WriteLine("get:" + ret.id);
    56. break;
    57. }
    58. }
    59. //避免两个同时创建对象,产生结果列表的错误
    60. if (ret == null&& dBmsqlSubs.Count<90)
    61. {
    62. DBmsqlSub dBmsqlSub = new DBmsqlSub();
    63. dBmsqlSubs.Add(dBmsqlSub);
    64. dBmsqlSub.setIsUser(true);
    65. ret = dBmsqlSub;
    66. Console.WriteLine("get:" + ret.id);
    67. }
    68. }
    69. return ret;
    70. }
    71. }
    72. }

    2.3.3

    1. using MySqlConnector;
    2. using System;
    3. using System.Collections.Generic;
    4. using System.Data;
    5. using System.Linq;
    6. using System.Text;
    7. using System.Threading.Tasks;
    8. namespace 数据库链接状态确认
    9. {
    10. public class Constand {
    11. public static string mesConnStr = "server=localhost;port=3306;database=db1;user id=root;password=123456;Charset=utf8;";
    12. }
    13. class DBmsqlSub
    14. {
    15. static int index = 0;
    16. public int id = 0;
    17. private bool isUser = false;
    18. private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    19. MySqlConnection mConn;
    20. MySqlCommand mCmd;
    21. public void setIsUser(bool value) {
    22. lock (this) {
    23. Console.WriteLine("index:" + index + " isuser:" + isUser+" setuser:"+ value);
    24. isUser = value;
    25. }
    26. }
    27. public MySqlDataReader MySqlDataReader { get; private set; }
    28. public DBmsqlSub()
    29. {
    30. id = index++;
    31. try
    32. {
    33. mConn = new MySqlConnection(Constand.mesConnStr);
    34. mConn.Open();
    35. mCmd = new MySqlCommand();
    36. mCmd.Connection = mConn;
    37. }
    38. catch (Exception e)
    39. {
    40. logger.Error(e.ToString());
    41. }
    42. }
    43. ~DBmsqlSub()
    44. {
    45. mConn.Close();
    46. }
    47. public void Close()
    48. {
    49. mConn.Close();
    50. }
    51. public bool isOpen()
    52. {
    53. if (mConn.State == ConnectionState.Closed)
    54. {
    55. mConn.Open();
    56. }
    57. if (mConn.State == ConnectionState.Open)
    58. {
    59. return true;
    60. }
    61. else
    62. {
    63. return false;
    64. }
    65. }
    66. public MySqlCommand getCmd()
    67. {
    68. return mCmd;
    69. }
    70. /// <summary>
    71. /// 如果没有链接,就直接链接
    72. /// </summary>
    73. private void conn()
    74. {
    75. if (mConn.State != ConnectionState.Open)
    76. {
    77. mConn.Open();
    78. }
    79. }
    80. /// <summary>
    81. /// 执行sql命令
    82. /// </summary>
    83. /// <param name="CommandText"></param>
    84. public void ExecuteNonQuery(String CommandText)
    85. {
    86. //setIsUser(true);
    87. mCmd.CommandText = CommandText;
    88. try
    89. {
    90. Console.WriteLine("id"+id);
    91. mCmd.ExecuteNonQuery();
    92. }
    93. catch (Exception ex)
    94. {
    95. logger.Error(ex.ToString());
    96. }
    97. finally {
    98. setIsUser(false);
    99. }
    100. }
    101. /// <summary>
    102. /// 插入数据,并返回插入数据的id
    103. /// </summary>
    104. /// <param name="CommandText"></param>
    105. /// <returns></returns>
    106. public int insertReturn(string CommandText)
    107. {
    108. setIsUser(true);
    109. int ret = 0;
    110. MySqlTransaction sqlTransaction = mConn.BeginTransaction();
    111. try
    112. {
    113. mCmd.CommandText = CommandText;
    114. object o = mCmd.ExecuteScalar();
    115. sqlTransaction.Commit();
    116. ret = int.Parse(o.ToString());
    117. }
    118. catch (Exception e)
    119. {
    120. logger.Error(e.ToString());
    121. sqlTransaction.Rollback();
    122. }
    123. finally
    124. {
    125. setIsUser(false);
    126. }
    127. return ret;
    128. }
    129. /// <summary>
    130. /// 执行并返回一个对象
    131. /// </summary>
    132. /// <param name="CommandText"></param>
    133. /// <returns></returns>
    134. public object ExecuteScalar(string CommandText)
    135. {
    136. setIsUser(true);
    137. object o = null;
    138. mCmd.CommandText = CommandText;
    139. try
    140. {
    141. o = mCmd.ExecuteScalar();
    142. }
    143. catch (Exception ex)
    144. {
    145. logger.Error(ex.ToString());
    146. }
    147. finally
    148. {
    149. setIsUser(false);
    150. }
    151. return o;
    152. }
    153. public MySqlDataReader ExecuteReader(string CommandText)
    154. {
    155. setIsUser(true);
    156. MySqlDataReader mySqlDataReader = null;
    157. mCmd.CommandText = CommandText;
    158. try
    159. {
    160. mySqlDataReader = mCmd.ExecuteReader();
    161. //mConn.Close();
    162. }
    163. catch (Exception ex)
    164. {
    165. logger.Error(ex.ToString());
    166. }
    167. finally
    168. {
    169. setIsUser(false);
    170. }
    171. return mySqlDataReader;
    172. }
    173. public ConnectionState getState() {
    174. return mConn.State;
    175. }
    176. public bool IsUrse() {
    177. return isUser;
    178. }
    179. }
    180. }

    2.3.4

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Text;
    5. using System.Threading.Tasks;
    6. namespace 数据库链接状态确认
    7. {
    8. /// <summary>
    9. /// 单件构象基类
    10. /// </summary>
    11. /// <typeparam name="T"></typeparam>
    12. public class Singleton<T> where T : new()
    13. {
    14. static T t = default(T);
    15. public static T getMy()
    16. {
    17. if (t == null)
    18. {
    19. t = new T();
    20. }
    21. return t;
    22. }
    23. }
    24. }

    运行结果:可用看出是几个链接对象在被循环的使用,也基本达到了直接的初衷,用尽可能少的链接,完成多线程的调用情景。

    1. id2
    2. index:5 isuser:True setuser:False
    3. index:5 isuser:False setuser:True
    4. index:5 isuser:True setuser:False
    5. get:3
    6. id3
    7. index:5 isuser:False setuser:True
    8. get:4
    9. id4
    10. index:5 isuser:True setuser:False
    11. index:5 isuser:False setuser:True
    12. get:2
    13. id2
    14. index:5 isuser:True setuser:False
    15. index:5 isuser:False setuser:True
    16. get:3
    17. id3

  • 相关阅读:
    你觉得工作开心重要还是赚钱重要?
    基于STC12C5A60S2系列1T 8051单片机的液晶显示器LCD1602显示两行常规字符应用
    视频融合平台EasyCVR综合管理平台加密机授权报错invalid character是什么原因
    uniapp优化h5项目-摇树优化,gzip压缩和删除console.log
    运用谷歌浏览器的开发者工具,模拟搜索引擎蜘蛛抓取网页
    Linux进程终止
    java 串口通讯
    SIT1050ISO 数字隔离接口芯片替代 ISO1050DUBR 电容隔离的CAN转发器
    Linux基础命令大全
    猿创征文|【JavaSE】Java概述与配置问题解决
  • 原文地址:https://blog.csdn.net/xie__jin__cheng/article/details/127104414